From 226405609e4e5f935eb0c819170c07dc94d7fe9d Mon Sep 17 00:00:00 2001 From: Patrick Pimentel Date: Mon, 8 Dec 2025 10:26:59 -0500 Subject: [PATCH] fix(auth-validator): [PM-22975] Client Version Validator - Updated with removal of cqrs approach in favor of static user checks. Also fixed tests --- src/Core/Entities/User.cs | 21 +++- ...eyManagementServiceCollectionExtensions.cs | 1 - .../GetMinimumClientVersionForUserQuery.cs | 23 ---- .../IGetMinimumClientVersionForUserQuery.cs | 8 -- .../RequestValidators/BaseRequestValidator.cs | 3 +- .../ClientVersionValidator.cs | 22 ++-- .../Factories/ApiApplicationFactory.cs | 4 +- .../Constants/TestEncryptionConstants.cs | 6 +- ...etMinimumClientVersionForUserQueryTests.cs | 72 ------------- .../EventsApplicationFactory.cs | 4 +- .../Endpoints/IdentityServerSsoTests.cs | 12 +-- .../Endpoints/IdentityServerTests.cs | 2 +- .../Endpoints/IdentityServerTwoFactorTests.cs | 8 +- .../ResourceOwnerPasswordValidatorTests.cs | 4 +- .../BaseRequestValidatorTests.cs | 6 +- .../ClientVersionValidatorTests.cs | 100 ++++++++++++++---- .../Factories/IdentityApplicationFactory.cs | 2 +- 17 files changed, 138 insertions(+), 160 deletions(-) delete mode 100644 src/Core/KeyManagement/Queries/GetMinimumClientVersionForUserQuery.cs delete mode 100644 src/Core/KeyManagement/Queries/Interfaces/IGetMinimumClientVersionForUserQuery.cs delete mode 100644 test/Core.Test/KeyManagement/Queries/GetMinimumClientVersionForUserQueryTests.cs diff --git a/src/Core/Entities/User.cs b/src/Core/Entities/User.cs index 510455886c..8045e7eaf1 100644 --- a/src/Core/Entities/User.cs +++ b/src/Core/Entities/User.cs @@ -212,14 +212,31 @@ public class User : ITableObject, IStorableSubscriber, IRevisable, ITwoFac return SecurityVersion ?? 1; } - public bool IsSetupForV2Encryption() + /// + /// Evaluates user state to determine if they are currently in a v2 encryption state. + /// + /// If the shape of their private key is v2 as well as has the proper security version then true, otherwise false + public bool HasV2Encryption() { return HasV2KeyShape() && IsSecurityVersionTwo(); } private bool HasV2KeyShape() { - return EncryptionParsing.GetEncryptionType(PrivateKey) == EncryptionType.XChaCha20Poly1305_B64; + if (string.IsNullOrEmpty(PrivateKey)) + { + return false; + } + + try + { + return EncryptionParsing.GetEncryptionType(PrivateKey) == EncryptionType.XChaCha20Poly1305_B64; + } + catch (ArgumentException) + { + // Invalid encryption string format - treat as not v2 + return false; + } } /// diff --git a/src/Core/KeyManagement/KeyManagementServiceCollectionExtensions.cs b/src/Core/KeyManagement/KeyManagementServiceCollectionExtensions.cs index f18d1c73ba..0e551c5d0e 100644 --- a/src/Core/KeyManagement/KeyManagementServiceCollectionExtensions.cs +++ b/src/Core/KeyManagement/KeyManagementServiceCollectionExtensions.cs @@ -26,6 +26,5 @@ public static class KeyManagementServiceCollectionExtensions private static void AddKeyManagementQueries(this IServiceCollection services) { services.AddScoped(); - services.AddScoped(); } } diff --git a/src/Core/KeyManagement/Queries/GetMinimumClientVersionForUserQuery.cs b/src/Core/KeyManagement/Queries/GetMinimumClientVersionForUserQuery.cs deleted file mode 100644 index f6fc64a4f7..0000000000 --- a/src/Core/KeyManagement/Queries/GetMinimumClientVersionForUserQuery.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Bit.Core.Entities; -using Bit.Core.KeyManagement.Queries.Interfaces; - -namespace Bit.Core.KeyManagement.Queries; - -public class GetMinimumClientVersionForUserQuery() - : IGetMinimumClientVersionForUserQuery -{ - public Task Run(User? user) - { - if (user == null) - { - return Task.FromResult(null); - } - - if (user.IsSetupForV2Encryption()) - { - return Task.FromResult(Constants.MinimumClientVersionForV2Encryption)!; - } - - return Task.FromResult(null); - } -} diff --git a/src/Core/KeyManagement/Queries/Interfaces/IGetMinimumClientVersionForUserQuery.cs b/src/Core/KeyManagement/Queries/Interfaces/IGetMinimumClientVersionForUserQuery.cs deleted file mode 100644 index 01deb460f1..0000000000 --- a/src/Core/KeyManagement/Queries/Interfaces/IGetMinimumClientVersionForUserQuery.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Bit.Core.Entities; - -namespace Bit.Core.KeyManagement.Queries.Interfaces; - -public interface IGetMinimumClientVersionForUserQuery -{ - Task Run(User? user); -} diff --git a/src/Identity/IdentityServer/RequestValidators/BaseRequestValidator.cs b/src/Identity/IdentityServer/RequestValidators/BaseRequestValidator.cs index e18b7165be..7c81b3b777 100644 --- a/src/Identity/IdentityServer/RequestValidators/BaseRequestValidator.cs +++ b/src/Identity/IdentityServer/RequestValidators/BaseRequestValidator.cs @@ -359,12 +359,11 @@ public abstract class BaseRequestValidator where T : class /// /// Validates whether the client version is compatible for the user attempting to authenticate. - /// New authentications only; refresh/device grants are handled elsewhere. /// /// true if the scheme successfully passed validation, otherwise false. private async Task ValidateClientVersionAsync(T context, CustomValidatorRequestContext validatorContext) { - var ok = await _clientVersionValidator.ValidateAsync(validatorContext.User, validatorContext); + var ok = _clientVersionValidator.ValidateAsync(validatorContext.User, validatorContext); if (ok) { return true; diff --git a/src/Identity/IdentityServer/RequestValidators/ClientVersionValidator.cs b/src/Identity/IdentityServer/RequestValidators/ClientVersionValidator.cs index 378b272a62..c160d81f11 100644 --- a/src/Identity/IdentityServer/RequestValidators/ClientVersionValidator.cs +++ b/src/Identity/IdentityServer/RequestValidators/ClientVersionValidator.cs @@ -1,6 +1,6 @@ using Bit.Core.Context; using Bit.Core.Entities; -using Bit.Core.KeyManagement.Queries.Interfaces; +using Bit.Core.KeyManagement; using Bit.Core.Models.Api; using Duende.IdentityServer.Validation; @@ -8,7 +8,7 @@ namespace Bit.Identity.IdentityServer.RequestValidators; public interface IClientVersionValidator { - Task ValidateAsync(User user, CustomValidatorRequestContext requestContext); + bool ValidateAsync(User user, CustomValidatorRequestContext requestContext); } /// @@ -22,24 +22,34 @@ public interface IClientVersionValidator /// If the header is omitted, then the validator returns that this request is valid. /// public class ClientVersionValidator( - ICurrentContext currentContext, - IGetMinimumClientVersionForUserQuery getMinimumClientVersionForUserQuery) + ICurrentContext currentContext) : IClientVersionValidator { private const string _upgradeMessage = "Please update your app to continue using Bitwarden"; + private const string _noUserMessage = "No user found while trying to validate client version"; - public async Task ValidateAsync(User? user, CustomValidatorRequestContext requestContext) + public bool ValidateAsync(User? user, CustomValidatorRequestContext requestContext) { // Do this nullish check because the base request validator currently is not // strict null checking. Once that gets fixed then we can see about making // the user not nullish checked. If they are null then the validator should fail. if (user == null) { + requestContext.ValidationErrorResult = new ValidationResult + { + Error = "no_user", + ErrorDescription = _noUserMessage, + IsError = true + }; + requestContext.CustomResponse = new Dictionary + { + { "ErrorModel", new ErrorResponseModel(_noUserMessage) } + }; return false; } Version? clientVersion = currentContext.ClientVersion; - Version? minVersion = await getMinimumClientVersionForUserQuery.Run(user); + Version? minVersion = user.HasV2Encryption() ? Constants.MinimumClientVersionForV2Encryption : null; // Allow through if headers are missing. // The minVersion should never be null because of where this validator is run. The user would diff --git a/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs b/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs index fe6fe7d463..7cc827bc6e 100644 --- a/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs +++ b/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs @@ -68,9 +68,9 @@ public class ApiApplicationFactory : WebApplicationFactoryBase UserAsymmetricKeys = new KeysRequestModel() { PublicKey = TestEncryptionConstants.PublicKey, - EncryptedPrivateKey = TestEncryptionConstants.V1EncryptedBase64 + EncryptedPrivateKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring }, - UserSymmetricKey = TestEncryptionConstants.V1EncryptedBase64, + UserSymmetricKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring, }); return await _identityApplicationFactory.TokenFromPasswordAsync(email, masterPasswordHash); diff --git a/test/Common/Constants/TestEncryptionConstants.cs b/test/Common/Constants/TestEncryptionConstants.cs index 45d3281865..aa30b20609 100644 --- a/test/Common/Constants/TestEncryptionConstants.cs +++ b/test/Common/Constants/TestEncryptionConstants.cs @@ -2,8 +2,8 @@ public static class TestEncryptionConstants { - // V1-style encrypted strings (AES-CBC-HMAC formats) accepted by validators - public const string V1EncryptedBase64 = "2.QmFzZTY0UGFydA==|QmFzZTY0UGFydA==|QmFzZTY0UGFydA=="; + // Intended for use as a V1 encrypted string, accepted by validators + public const string AES256_CBC_HMAC_Encstring = "2.QmFzZTY0UGFydA==|QmFzZTY0UGFydA==|QmFzZTY0UGFydA=="; // Public key test placeholder public const string PublicKey = "pk_test"; @@ -15,5 +15,3 @@ public static class TestEncryptionConstants public const string V2WrappedSigningKey = "7.cose_signing"; public const string V2VerifyingKey = "vk"; } - - diff --git a/test/Core.Test/KeyManagement/Queries/GetMinimumClientVersionForUserQueryTests.cs b/test/Core.Test/KeyManagement/Queries/GetMinimumClientVersionForUserQueryTests.cs deleted file mode 100644 index 010eb23586..0000000000 --- a/test/Core.Test/KeyManagement/Queries/GetMinimumClientVersionForUserQueryTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Bit.Core.Entities; -using Bit.Core.KeyManagement.Queries; -using Bit.Test.Common.Constants; -using Xunit; - -namespace Bit.Core.Test.KeyManagement.Queries; - -public class GetMinimumClientVersionForUserQueryTests -{ - [Fact] - public async Task Run_ReturnsMinVersion_ForV2User() - { - var sut = new GetMinimumClientVersionForUserQuery(); - var version = await sut.Run(new User - { - SecurityVersion = 2, - PrivateKey = TestEncryptionConstants.V2PrivateKey, - }); - Assert.Equal(Core.KeyManagement.Constants.MinimumClientVersionForV2Encryption, version); - } - - [Fact] - public async Task Run_ReturnsNull_ForV1User() - { - var sut = new GetMinimumClientVersionForUserQuery(); - var version = await sut.Run(new User - { - SecurityVersion = 1, - PrivateKey = TestEncryptionConstants.V1EncryptedBase64, - }); - Assert.Null(version); - } - - [Fact] - public async Task Run_ReturnsNull_ForSecurityVersion1ButPrivateKeyV2User() - { - var sut = new GetMinimumClientVersionForUserQuery(); - var version = await sut.Run(new User - { - SecurityVersion = 1, - PrivateKey = TestEncryptionConstants.V2PrivateKey, - }); - Assert.Null(version); - } - - [Fact] - public async Task Run_ReturnsNull_ForPrivateKeyV1ButSecurityVersion2User() - { - var sut = new GetMinimumClientVersionForUserQuery(); - var version = await sut.Run(new User - { - SecurityVersion = 2, - PrivateKey = TestEncryptionConstants.V1EncryptedBase64, - }); - Assert.Null(version); - } - - - [Fact] - public async Task Run_ReturnsNull_ForV1UserWithNull() - { - var sut = new GetMinimumClientVersionForUserQuery(); - var version = await sut.Run(new User - { - SecurityVersion = null, - PrivateKey = TestEncryptionConstants.V2PrivateKey, - }); - Assert.Null(version); - } -} - - diff --git a/test/Events.IntegrationTest/EventsApplicationFactory.cs b/test/Events.IntegrationTest/EventsApplicationFactory.cs index 45e89f7dc6..3530d0aa6c 100644 --- a/test/Events.IntegrationTest/EventsApplicationFactory.cs +++ b/test/Events.IntegrationTest/EventsApplicationFactory.cs @@ -60,9 +60,9 @@ public class EventsApplicationFactory : WebApplicationFactoryBase UserAsymmetricKeys = new KeysRequestModel() { PublicKey = TestEncryptionConstants.PublicKey, - EncryptedPrivateKey = TestEncryptionConstants.V1EncryptedBase64 + EncryptedPrivateKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring }, - UserSymmetricKey = TestEncryptionConstants.V1EncryptedBase64, + UserSymmetricKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring, }); return await _identityApplicationFactory.TokenFromPasswordAsync(email, masterPasswordHash); diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs index 010ac70d27..2effe8cb43 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs @@ -313,8 +313,8 @@ public class IdentityServerSsoTests var user = await factory.Services.GetRequiredService().GetByEmailAsync(TestEmail); Assert.NotNull(user); - const string expectedPrivateKey = TestEncryptionConstants.V1EncryptedBase64; - const string expectedUserKey = TestEncryptionConstants.V1EncryptedBase64; + const string expectedPrivateKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring; + const string expectedUserKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring; var device = await deviceRepository.CreateAsync(new Device { @@ -323,7 +323,7 @@ public class IdentityServerSsoTests Name = "Thing", UserId = user.Id, EncryptedPrivateKey = expectedPrivateKey, - EncryptedPublicKey = TestEncryptionConstants.V1EncryptedBase64, + EncryptedPublicKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring, EncryptedUserKey = expectedUserKey, }); @@ -630,7 +630,7 @@ public class IdentityServerSsoTests factory.SubstituteService(svc => { svc.ValidateAsync(Arg.Any(), Arg.Any()) - .Returns(Task.FromResult(true)); + .Returns(true); }); var authorizationCode = new AuthorizationCode @@ -662,9 +662,9 @@ public class IdentityServerSsoTests UserAsymmetricKeys = new KeysRequestModel() { PublicKey = TestEncryptionConstants.PublicKey, - EncryptedPrivateKey = TestEncryptionConstants.V1EncryptedBase64 // v1-format so parsing succeeds and user is treated as v1 + EncryptedPrivateKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring // v1-format so parsing succeeds and user is treated as v1 }, - UserSymmetricKey = TestEncryptionConstants.V1EncryptedBase64, + UserSymmetricKey = TestEncryptionConstants.AES256_CBC_HMAC_Encstring, }); var organizationRepository = factory.Services.GetRequiredService(); diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs index fb298b9677..7b42f7464e 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs @@ -37,7 +37,7 @@ public class IdentityServerTests : IClassFixture _factory.SubstituteService(svc => { svc.ValidateAsync(Arg.Any(), Arg.Any()) - .Returns(Task.FromResult(true)); + .Returns(true); }); ReinitializeDbForTests(_factory); diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs index 0e6f9931e6..d0d35f5d7b 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs @@ -388,9 +388,9 @@ public class IdentityServerTwoFactorTests : IClassFixture(); diff --git a/test/Identity.IntegrationTest/RequestValidation/VaultAccess/ResourceOwnerPasswordValidatorTests.cs b/test/Identity.IntegrationTest/RequestValidation/VaultAccess/ResourceOwnerPasswordValidatorTests.cs index 90391ff699..54fb80eed0 100644 --- a/test/Identity.IntegrationTest/RequestValidation/VaultAccess/ResourceOwnerPasswordValidatorTests.cs +++ b/test/Identity.IntegrationTest/RequestValidation/VaultAccess/ResourceOwnerPasswordValidatorTests.cs @@ -614,9 +614,9 @@ public class ResourceOwnerPasswordValidatorTests : IClassFixture(), Arg.Any()) - .Returns(Task.FromResult(true)); + .Returns(true); } private void SetupRecoveryCodeSupportForSsoRequiredUsersFeatureFlag(bool recoveryCodeSupportEnabled) @@ -1296,7 +1296,7 @@ public class BaseRequestValidatorTests // Make client version validation succeed but ensure it's invoked _clientVersionValidator .ValidateAsync(requestContext.User, requestContext) - .Returns(Task.FromResult(true)); + .Returns(true); // Ensure SSO requirement triggers an early stop after version validation to avoid success path setup _policyService.AnyPoliciesApplicableToUserAsync( @@ -1307,7 +1307,7 @@ public class BaseRequestValidatorTests await _sut.ValidateAsync(context); // Assert - await _clientVersionValidator.Received(1) + _clientVersionValidator.Received(1) .ValidateAsync(requestContext.User, requestContext); } diff --git a/test/Identity.Test/IdentityServer/RequestValidators/ClientVersionValidatorTests.cs b/test/Identity.Test/IdentityServer/RequestValidators/ClientVersionValidatorTests.cs index 494fb79d25..6adc997f79 100644 --- a/test/Identity.Test/IdentityServer/RequestValidators/ClientVersionValidatorTests.cs +++ b/test/Identity.Test/IdentityServer/RequestValidators/ClientVersionValidatorTests.cs @@ -1,7 +1,7 @@ using Bit.Core.Context; using Bit.Core.Entities; -using Bit.Core.KeyManagement.Queries.Interfaces; using Bit.Identity.IdentityServer.RequestValidators; +using Bit.Test.Common.Constants; using NSubstitute; using Xunit; @@ -9,34 +9,49 @@ namespace Bit.Identity.Test.IdentityServer.RequestValidators; public class ClientVersionValidatorTests { - private static ICurrentContext MakeContext(Version version) + private static ICurrentContext MakeContext(Version? version) { var ctx = Substitute.For(); ctx.ClientVersion = version; return ctx; } - private static IGetMinimumClientVersionForUserQuery MakeMinQuery(Version? v) + private static User MakeValidV2User() { - var q = Substitute.For(); - q.Run(Arg.Any()).Returns(Task.FromResult(v)); - return q; + return new User + { + PrivateKey = TestEncryptionConstants.V2PrivateKey, + SecurityVersion = 2 + }; } [Fact] - public async Task Allows_When_NoMinVersion() + public void Allows_When_ClientMeetsMinimumVersion() { - var sut = new ClientVersionValidator(MakeContext(new Version("2025.1.0")), MakeMinQuery(null)); - var ok = await sut.ValidateAsync(new User(), new Bit.Identity.IdentityServer.CustomValidatorRequestContext()); + // Arrange + var sut = new ClientVersionValidator(MakeContext(new Version("2025.11.0"))); + var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); + var user = MakeValidV2User(); + + // Act + var ok = sut.ValidateAsync(user, ctx); + + // Assert Assert.True(ok); } [Fact] - public async Task Blocks_When_ClientTooOld() + public void Blocks_When_ClientTooOld() { - var sut = new ClientVersionValidator(MakeContext(new Version("2025.10.0")), MakeMinQuery(new Version("2025.11.0"))); + // Arrange + var sut = new ClientVersionValidator(MakeContext(new Version("2025.10.0"))); var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); - var ok = await sut.ValidateAsync(new User(), ctx); + var user = MakeValidV2User(); + + // Act + var ok = sut.ValidateAsync(user, ctx); + + // Assert Assert.False(ok); Assert.NotNull(ctx.ValidationErrorResult); Assert.True(ctx.ValidationErrorResult.IsError); @@ -44,23 +59,66 @@ public class ClientVersionValidatorTests } [Fact] - public async Task Allows_When_ClientMeetsMin() + public void Blocks_When_NullUser() { - var sut = new ClientVersionValidator(MakeContext(new Version("2025.11.0")), MakeMinQuery(new Version("2025.11.0"))); - var ok = await sut.ValidateAsync(new User(), new Bit.Identity.IdentityServer.CustomValidatorRequestContext()); + // Arrange + var sut = new ClientVersionValidator(MakeContext(new Version("2025.11.0"))); + var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); + User? user = null; + + // Act + var ok = sut.ValidateAsync(user, ctx); + + // Assert + Assert.False(ok); + Assert.NotNull(ctx.ValidationErrorResult); + Assert.True(ctx.ValidationErrorResult.IsError); + Assert.Equal("no_user", ctx.ValidationErrorResult.Error); + } + + [Fact] + public void Allows_When_NoPrivateKey() + { + // Arrange + var sut = new ClientVersionValidator(MakeContext(new Version("2025.11.0"))); + var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); + var user = MakeValidV2User(); + user.PrivateKey = null; + + // Act + var ok = sut.ValidateAsync(user, ctx); + + // Assert Assert.True(ok); } [Fact] - public async Task Allows_When_ClientVersionHeaderMissing() + public void Allows_When_NoSecurityVersion() { - // Do not set ClientVersion on the context (remains null) and ensure - var ctx = Substitute.For(); - var minQuery = MakeMinQuery(new Version("2025.11.0")); - var sut = new ClientVersionValidator(ctx, minQuery); + // Arrange + var sut = new ClientVersionValidator(MakeContext(new Version("2025.11.0"))); + var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); - var ok = await sut.ValidateAsync(new User(), new Bit.Identity.IdentityServer.CustomValidatorRequestContext()); + var user = MakeValidV2User(); + user.SecurityVersion = null; + // Act + var ok = sut.ValidateAsync(user, ctx); + // Assert + Assert.True(ok); + } + [Fact] + public void Allows_When_ClientVersionHeaderMissing() + { + // Arrange + var sut = new ClientVersionValidator(MakeContext(null)); + var ctx = new Bit.Identity.IdentityServer.CustomValidatorRequestContext(); + var user = MakeValidV2User(); + + // Act + var ok = sut.ValidateAsync(user, ctx); + + // Assert Assert.True(ok); } } diff --git a/test/IntegrationTestCommon/Factories/IdentityApplicationFactory.cs b/test/IntegrationTestCommon/Factories/IdentityApplicationFactory.cs index d228ed38e3..1304d66f67 100644 --- a/test/IntegrationTestCommon/Factories/IdentityApplicationFactory.cs +++ b/test/IntegrationTestCommon/Factories/IdentityApplicationFactory.cs @@ -55,7 +55,7 @@ public class IdentityApplicationFactory : WebApplicationFactoryBase SubstituteService(svc => { svc.ValidateAsync(Arg.Any(), Arg.Any()) - .Returns(Task.FromResult(true)); + .Returns(true); }); }