1
0
mirror of https://github.com/bitwarden/server synced 2026-02-25 00:52:57 +00:00

feat(auth-validator): [Auth/PM-22975] Client Version Validator (#6588)

* feat(auth-validator): [PM-22975] Client Version Validator - Implementation.

* test(auth-validator): [PM-22975] Client Version Validator - Added tests.
This commit is contained in:
Patrick-Pimentel-Bitwarden
2026-02-23 10:00:10 -05:00
committed by GitHub
parent b5554c6030
commit 3dbd17f61d
27 changed files with 732 additions and 83 deletions

View File

@@ -58,6 +58,7 @@ public class BaseRequestValidatorTests
private readonly IAuthRequestRepository _authRequestRepository;
private readonly IMailService _mailService;
private readonly IUserAccountKeysQuery _userAccountKeysQuery;
private readonly IClientVersionValidator _clientVersionValidator;
private readonly BaseRequestValidatorTestWrapper _sut;
@@ -82,6 +83,7 @@ public class BaseRequestValidatorTests
_authRequestRepository = Substitute.For<IAuthRequestRepository>();
_mailService = Substitute.For<IMailService>();
_userAccountKeysQuery = Substitute.For<IUserAccountKeysQuery>();
_clientVersionValidator = Substitute.For<IClientVersionValidator>();
_sut = new BaseRequestValidatorTestWrapper(
_userManager,
@@ -102,7 +104,13 @@ public class BaseRequestValidatorTests
_policyRequirementQuery,
_authRequestRepository,
_mailService,
_userAccountKeysQuery);
_userAccountKeysQuery,
_clientVersionValidator);
// Default client version validator behavior: allow to pass unless a test overrides.
_clientVersionValidator
.Validate(Arg.Any<User>(), Arg.Any<CustomValidatorRequestContext>())
.Returns(true);
}
/* Logic path
@@ -1266,6 +1274,38 @@ public class BaseRequestValidatorTests
"TwoFactorRecoveryRequested flag should be set for audit/logging");
}
[Theory]
[BitAutoData]
public async Task ValidateAsync_ClientVersionValidator_IsInvoked(
[AuthFixtures.ValidatedTokenRequest] ValidatedTokenRequest tokenRequest,
[AuthFixtures.CustomValidatorRequestContext] CustomValidatorRequestContext requestContext,
GrantValidationResult grantResult)
{
// Arrange
var context = CreateContext(tokenRequest, requestContext, grantResult);
_sut.isValid = true; // ensure initial context validation passes
// Force a grant type that will evaluate SSO after client version validation
context.ValidatedTokenRequest.GrantType = "password";
// Make client version validation succeed but ensure it's invoked
_clientVersionValidator
.Validate(requestContext.User, requestContext)
.Returns(true);
// Ensure SSO requirement triggers an early stop after version validation to avoid success path setup
_policyService.AnyPoliciesApplicableToUserAsync(
Arg.Any<Guid>(), PolicyType.RequireSso, OrganizationUserStatusType.Confirmed)
.Returns(Task.FromResult(true));
// Act
await _sut.ValidateAsync(context);
// Assert
_clientVersionValidator.Received(1)
.Validate(requestContext.User, requestContext);
}
/// <summary>
/// Tests that when SSO validation returns a custom response, (e.g., with organization identifier),
/// that custom response is properly propagated to the result.