mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 15:42:48 -05:00
[PM-18237] Add RequireSsoPolicyRequirement (#5655)
* Add RequireSsoPolicyRequirement and its factory to enforce SSO policies * Enhance WebAuthnController to support RequireSsoPolicyRequirement with feature flag integration. Update tests to validate behavior when SSO policies are applicable. * Integrate IPolicyRequirementQuery into request validators to support RequireSsoPolicyRequirement. Update validation logic to check SSO policies based on feature flag. * Refactor RequireSsoPolicyRequirementFactoryTests to improve test coverage for SSO policies. Add tests for handling both valid and invalid policies in CanUsePasskeyLogin and SsoRequired methods. * Remove ExemptStatuses property from RequireSsoPolicyRequirementFactory to use default values from BasePolicyRequirementFactory * Restore ValidateRequireSsoPolicyDisabledOrNotApplicable * Refactor RequireSsoPolicyRequirement to update CanUsePasskeyLogin and SsoRequired properties to use init-only setters * Refactor RequireSsoPolicyRequirementFactoryTests to enhance test clarity * Refactor BaseRequestValidatorTests to improve test clarity * Refactor WebAuthnController to replace SSO policy validation with PolicyRequirement check * Refactor BaseRequestValidator to replace SSO policy validation with PolicyRequirement check * Refactor WebAuthnControllerTests to update test method names and adjust policy requirement checks * Add tests for AttestationOptions and Post methods in WebAuthnControllerTests to validate scenario where SSO is not required * Refactor RequireSsoPolicyRequirement initialization * Refactor SSO requirement check for improved readability * Rename test methods in RequireSsoPolicyRequirementFactoryTests for clarity on exempt status conditions * Update RequireSsoPolicyRequirement to refine user status checks for SSO policy requirements
This commit is contained in:
@ -4,6 +4,7 @@ using Bit.Api.Auth.Models.Response.WebAuthn;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Core;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Api.Response.Accounts;
|
||||
@ -31,6 +32,8 @@ public class WebAuthnController : Controller
|
||||
private readonly ICreateWebAuthnLoginCredentialCommand _createWebAuthnLoginCredentialCommand;
|
||||
private readonly IAssertWebAuthnLoginCredentialCommand _assertWebAuthnLoginCredentialCommand;
|
||||
private readonly IGetWebAuthnLoginCredentialAssertionOptionsCommand _getWebAuthnLoginCredentialAssertionOptionsCommand;
|
||||
private readonly IPolicyRequirementQuery _policyRequirementQuery;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
public WebAuthnController(
|
||||
IUserService userService,
|
||||
@ -41,7 +44,9 @@ public class WebAuthnController : Controller
|
||||
IGetWebAuthnLoginCredentialCreateOptionsCommand getWebAuthnLoginCredentialCreateOptionsCommand,
|
||||
ICreateWebAuthnLoginCredentialCommand createWebAuthnLoginCredentialCommand,
|
||||
IAssertWebAuthnLoginCredentialCommand assertWebAuthnLoginCredentialCommand,
|
||||
IGetWebAuthnLoginCredentialAssertionOptionsCommand getWebAuthnLoginCredentialAssertionOptionsCommand)
|
||||
IGetWebAuthnLoginCredentialAssertionOptionsCommand getWebAuthnLoginCredentialAssertionOptionsCommand,
|
||||
IPolicyRequirementQuery policyRequirementQuery,
|
||||
IFeatureService featureService)
|
||||
{
|
||||
_userService = userService;
|
||||
_policyService = policyService;
|
||||
@ -52,7 +57,8 @@ public class WebAuthnController : Controller
|
||||
_createWebAuthnLoginCredentialCommand = createWebAuthnLoginCredentialCommand;
|
||||
_assertWebAuthnLoginCredentialCommand = assertWebAuthnLoginCredentialCommand;
|
||||
_getWebAuthnLoginCredentialAssertionOptionsCommand = getWebAuthnLoginCredentialAssertionOptionsCommand;
|
||||
|
||||
_policyRequirementQuery = policyRequirementQuery;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
@ -68,7 +74,7 @@ public class WebAuthnController : Controller
|
||||
public async Task<WebAuthnCredentialCreateOptionsResponseModel> AttestationOptions([FromBody] SecretVerificationRequestModel model)
|
||||
{
|
||||
var user = await VerifyUserAsync(model);
|
||||
await ValidateRequireSsoPolicyDisabledOrNotApplicable(user.Id);
|
||||
await ValidateIfUserCanUsePasskeyLogin(user.Id);
|
||||
var options = await _getWebAuthnLoginCredentialCreateOptionsCommand.GetWebAuthnLoginCredentialCreateOptionsAsync(user);
|
||||
|
||||
var tokenable = new WebAuthnCredentialCreateOptionsTokenable(user, options);
|
||||
@ -101,7 +107,7 @@ public class WebAuthnController : Controller
|
||||
public async Task Post([FromBody] WebAuthnLoginCredentialCreateRequestModel model)
|
||||
{
|
||||
var user = await GetUserAsync();
|
||||
await ValidateRequireSsoPolicyDisabledOrNotApplicable(user.Id);
|
||||
await ValidateIfUserCanUsePasskeyLogin(user.Id);
|
||||
var tokenable = _createOptionsDataProtector.Unprotect(model.Token);
|
||||
|
||||
if (!tokenable.TokenIsValid(user))
|
||||
@ -126,6 +132,22 @@ public class WebAuthnController : Controller
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ValidateIfUserCanUsePasskeyLogin(Guid userId)
|
||||
{
|
||||
if (!_featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements))
|
||||
{
|
||||
await ValidateRequireSsoPolicyDisabledOrNotApplicable(userId);
|
||||
return;
|
||||
}
|
||||
|
||||
var requireSsoPolicyRequirement = await _policyRequirementQuery.GetAsync<RequireSsoPolicyRequirement>(userId);
|
||||
|
||||
if (!requireSsoPolicyRequirement.CanUsePasskeyLogin)
|
||||
{
|
||||
throw new BadRequestException("Passkeys cannot be created for your account. SSO login is required.");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut()]
|
||||
public async Task UpdateCredential([FromBody] WebAuthnLoginCredentialUpdateRequestModel model)
|
||||
{
|
||||
|
Reference in New Issue
Block a user