using Bit.Api.Auth.Models.Request.WebAuthn; using Bit.Api.KeyManagement.Validators; using Bit.Core.Auth.Entities; using Bit.Core.Auth.Repositories; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Api.Test.KeyManagement.Validators; [SutProviderCustomize] public class WebAuthnLoginKeyRotationValidatorTests { [Theory] [BitAutoData] public async Task ValidateAsync_Succeeds_ReturnsValidCredentials( SutProvider sutProvider, User user, IEnumerable webauthnRotateCredentialData) { var guid = Guid.NewGuid(); var webauthnKeysToRotate = webauthnRotateCredentialData.Select(e => new WebAuthnLoginRotateKeyRequestModel { Id = guid, EncryptedPublicKey = e.EncryptedPublicKey, EncryptedUserKey = e.EncryptedUserKey }).ToList(); var data = new WebAuthnCredential { Id = guid, SupportsPrf = true, EncryptedPublicKey = "TestKey", EncryptedUserKey = "Test" }; sutProvider.GetDependency().GetManyByUserIdAsync(user.Id) .Returns(new List { data }); var result = await sutProvider.Sut.ValidateAsync(user, webauthnKeysToRotate); Assert.Single(result); Assert.Equal(guid, result.First().Id); } [Theory] [BitAutoData] public async Task ValidateAsync_DoesNotSupportPRF_Ignores( SutProvider sutProvider, User user, IEnumerable webauthnRotateCredentialData) { var guid = Guid.NewGuid(); var webauthnKeysToRotate = webauthnRotateCredentialData.Select(e => new WebAuthnLoginRotateKeyRequestModel { Id = guid, EncryptedUserKey = e.EncryptedUserKey, EncryptedPublicKey = e.EncryptedPublicKey, }).ToList(); var data = new WebAuthnCredential { Id = guid, EncryptedUserKey = "Test", EncryptedPublicKey = "TestKey" }; sutProvider.GetDependency().GetManyByUserIdAsync(user.Id) .Returns(new List { data }); var result = await sutProvider.Sut.ValidateAsync(user, webauthnKeysToRotate); Assert.Empty(result); } [Theory] [BitAutoData] public async Task ValidateAsync_WrongWebAuthnKeys_Throws( SutProvider sutProvider, User user, IEnumerable webauthnRotateCredentialData) { var webauthnKeysToRotate = webauthnRotateCredentialData.Select(e => new WebAuthnLoginRotateKeyRequestModel { Id = Guid.Parse("00000000-0000-0000-0000-000000000001"), EncryptedPublicKey = e.EncryptedPublicKey, EncryptedUserKey = e.EncryptedUserKey }).ToList(); var data = new WebAuthnCredential { Id = Guid.Parse("00000000-0000-0000-0000-000000000002"), SupportsPrf = true, EncryptedPublicKey = "TestKey", EncryptedUserKey = "Test" }; sutProvider.GetDependency().GetManyByUserIdAsync(user.Id).Returns(new List { data }); await Assert.ThrowsAsync(async () => await sutProvider.Sut.ValidateAsync(user, webauthnKeysToRotate)); } [Theory] [BitAutoData] public async Task ValidateAsync_NullUserKey_Throws( SutProvider sutProvider, User user, IEnumerable webauthnRotateCredentialData) { var guid = Guid.NewGuid(); var webauthnKeysToRotate = webauthnRotateCredentialData.Select(e => new WebAuthnLoginRotateKeyRequestModel { Id = guid, EncryptedPublicKey = e.EncryptedPublicKey, }).ToList(); var data = new WebAuthnCredential { Id = guid, SupportsPrf = true, EncryptedPublicKey = "TestKey", EncryptedUserKey = "Test" }; sutProvider.GetDependency().GetManyByUserIdAsync(user.Id).Returns(new List { data }); await Assert.ThrowsAsync(async () => await sutProvider.Sut.ValidateAsync(user, webauthnKeysToRotate)); } [Theory] [BitAutoData] public async Task ValidateAsync_NullPublicKey_Throws( SutProvider sutProvider, User user, IEnumerable webauthnRotateCredentialData) { var guid = Guid.NewGuid(); var webauthnKeysToRotate = webauthnRotateCredentialData.Select(e => new WebAuthnLoginRotateKeyRequestModel { Id = guid, EncryptedUserKey = e.EncryptedUserKey, }).ToList(); var data = new WebAuthnCredential { Id = guid, SupportsPrf = true, EncryptedPublicKey = "TestKey", EncryptedUserKey = "Test" }; sutProvider.GetDependency().GetManyByUserIdAsync(user.Id).Returns(new List { data }); await Assert.ThrowsAsync(async () => await sutProvider.Sut.ValidateAsync(user, webauthnKeysToRotate)); } }