mirror of
https://github.com/bitwarden/mobile
synced 2025-12-22 19:23:58 +00:00
* PM-6441 Implement passkeys User Verification * PM-6441 Reorganized UserVerificationMediatorService so everything is not in the same file * PM-6441 Fix Unit tests * PM-6441 Refactor UserVerification on Fido2Authenticator and Client services to be of an enum type so we can see which specific preference the RP sent and to be passed into the user verification mediator service to perform the correct flow depending on that. Also updated Unit tests. * PM-6441 Changed user verification logic a bit so if preference is Preferred and the app has the ability to verify the user then enforce required UV and fix issue on on Discouraged to take into account MP reprompt
117 lines
4.6 KiB
C#
117 lines
4.6 KiB
C#
using System.Threading.Tasks;
|
|
using Bit.Core.Abstractions;
|
|
using Bit.Core.Utilities.Fido2;
|
|
using Xunit;
|
|
|
|
namespace Bit.Core.Test.Utilities.Fido2
|
|
{
|
|
public class Fido2GetAssertionUserInterfaceTests
|
|
{
|
|
[Fact]
|
|
public async Task PickCredentialAsync_ThrowsNotAllowed_PrePickedCredentialDoesNotMatch()
|
|
{
|
|
// Arrange
|
|
var userInterface = new Fido2GetAssertionUserInterface("cipherId", false, null, DefaultHasVaultBeenUnlockedInThisTransaction, DefaultVerifyUserAsync);
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<NotAllowedError>(() => userInterface.PickCredentialAsync(new Fido2GetAssertionUserInterfaceCredential[] { CreateCredential("notMatching", Fido2UserVerificationPreference.Discouraged) }));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PickCredentialAsync_ReturnPrePickedCredential_CredentialsMatch()
|
|
{
|
|
// Arrange
|
|
var userInterface = new Fido2GetAssertionUserInterface("cipherId", false, null, DefaultHasVaultBeenUnlockedInThisTransaction, DefaultVerifyUserAsync);
|
|
|
|
// Act
|
|
var result = await userInterface.PickCredentialAsync(new Fido2GetAssertionUserInterfaceCredential[]
|
|
{
|
|
CreateCredential("cipherId", Fido2UserVerificationPreference.Discouraged),
|
|
CreateCredential("cipherId2", Fido2UserVerificationPreference.Required)
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal("cipherId", result.CipherId);
|
|
Assert.False(result.UserVerified);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PickCredentialAsync_CallsUserVerificationCallback_UserIsAlreadyVerified()
|
|
{
|
|
// Arrange
|
|
var called = false;
|
|
var userInterface = new Fido2GetAssertionUserInterface("cipherId", false, null, DefaultHasVaultBeenUnlockedInThisTransaction, (_, __) =>
|
|
{
|
|
called = true;
|
|
return Task.FromResult(true);
|
|
});
|
|
|
|
// Act
|
|
var result = await userInterface.PickCredentialAsync(new Fido2GetAssertionUserInterfaceCredential[]
|
|
{
|
|
CreateCredential("cipherId", Fido2UserVerificationPreference.Required),
|
|
CreateCredential("cipherId2", Fido2UserVerificationPreference.Discouraged)
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal("cipherId", result.CipherId);
|
|
Assert.True(result.UserVerified);
|
|
Assert.True(called);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PickCredentialAsync_DoesNotCallUserVerificationCallback_UserVerificationIsAlreadyPerformed()
|
|
{
|
|
// Arrange
|
|
var called = false;
|
|
var userInterface = new Fido2GetAssertionUserInterface("cipherId2", true, null, DefaultHasVaultBeenUnlockedInThisTransaction, (_, __) =>
|
|
{
|
|
called = true;
|
|
return Task.FromResult(true);
|
|
});
|
|
|
|
// Act
|
|
var result = await userInterface.PickCredentialAsync(new Fido2GetAssertionUserInterfaceCredential[]
|
|
{
|
|
CreateCredential("cipherId", Fido2UserVerificationPreference.Required),
|
|
CreateCredential("cipherId2", Fido2UserVerificationPreference.Discouraged)
|
|
});
|
|
|
|
// Assert
|
|
Assert.Equal("cipherId2", result.CipherId);
|
|
Assert.True(result.UserVerified);
|
|
Assert.False(called);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task EnsureUnlockedVaultAsync_CallsCallback()
|
|
{
|
|
// Arrange
|
|
var called = false;
|
|
var callback = () => { called = true; return Task.CompletedTask; };
|
|
var userInterface = new Fido2GetAssertionUserInterface("cipherId", false, callback, DefaultHasVaultBeenUnlockedInThisTransaction, DefaultVerifyUserAsync);
|
|
|
|
// Act
|
|
await userInterface.EnsureUnlockedVaultAsync();
|
|
|
|
// Assert
|
|
Assert.True(called);
|
|
Assert.True(userInterface.HasVaultBeenUnlockedInThisTransaction);
|
|
}
|
|
|
|
private Fido2GetAssertionUserInterfaceCredential CreateCredential(string cipherId, Fido2UserVerificationPreference userVerificationPreference)
|
|
{
|
|
return new Fido2GetAssertionUserInterfaceCredential
|
|
{
|
|
CipherId = cipherId,
|
|
UserVerificationPreference = userVerificationPreference
|
|
};
|
|
}
|
|
|
|
private bool DefaultHasVaultBeenUnlockedInThisTransaction() => true;
|
|
|
|
private Task<bool> DefaultVerifyUserAsync(string _, Fido2UserVerificationPreference __) => Task.FromResult(false);
|
|
|
|
}
|
|
}
|