1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-06-26 10:36:21 +02:00
bitwarden-mobile/src/Core/Utilities/Fido2/Fido2GetAssertionUserInterface.cs
Federico Maccaroni 4292542155
[PM-6466] Implement passkeys User Verification (#3044)
* 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
2024-03-06 12:32:39 -03:00

59 lines
2.6 KiB
C#

using Bit.Core.Abstractions;
namespace Bit.Core.Utilities.Fido2
{
/// <summary>
/// This implementation is used when all interactions are handled by the operating system.
/// Most often the user has already picked a credential by the time the Authenticator is called,
/// so this class just returns those values.
///
/// This class has no corresponding attestation variant, because that operation requires that the
/// user interacts with the app directly.
/// </summary>
public class Fido2GetAssertionUserInterface : IFido2GetAssertionUserInterface
{
private readonly string _cipherId;
private readonly bool _userVerified = false;
private readonly Func<Task> _ensureUnlockedVaultCallback;
private readonly Func<bool> _hasVaultBeenUnlockedInThisTransaction;
private readonly Func<string, Fido2UserVerificationPreference, Task<bool>> _verifyUserCallback;
/// <param name="cipherId">The cipherId for the credential that the user has already picker</param>
/// <param name="userVerified">True if the user has already been verified by the operating system</param>
public Fido2GetAssertionUserInterface(string cipherId,
bool userVerified,
Func<Task> ensureUnlockedVaultCallback,
Func<bool> hasVaultBeenUnlockedInThisTransaction,
Func<string, Fido2UserVerificationPreference, Task<bool>> verifyUserCallback)
{
_cipherId = cipherId;
_userVerified = userVerified;
_ensureUnlockedVaultCallback = ensureUnlockedVaultCallback;
_hasVaultBeenUnlockedInThisTransaction = hasVaultBeenUnlockedInThisTransaction;
_verifyUserCallback = verifyUserCallback;
}
public bool HasVaultBeenUnlockedInThisTransaction { get; private set; }
public async Task<(string CipherId, bool UserVerified)> PickCredentialAsync(Fido2GetAssertionUserInterfaceCredential[] credentials)
{
if (credentials.Length == 0 || !credentials.Any(c => c.CipherId == _cipherId))
{
throw new NotAllowedError();
}
var credential = credentials.First(c => c.CipherId == _cipherId);
var verified = _userVerified || await _verifyUserCallback(_cipherId, credential.UserVerificationPreference);
return (CipherId: _cipherId, UserVerified: verified);
}
public async Task EnsureUnlockedVaultAsync()
{
await _ensureUnlockedVaultCallback();
HasVaultBeenUnlockedInThisTransaction = _hasVaultBeenUnlockedInThisTransaction();
}
}
}