1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-25 23:02:17 -05:00
bitwarden/src/Api/KeyManagement/Validators/WebAuthnLoginKeyRotationValidator.cs
Jake Fink 83e06c9241
[PM-19523] Filter expected webauthn keys for rotations by prf enabled (#5566)
* filter expected webauthn keys for rotations by prf enabled

* fix and add tests

* format
2025-04-03 11:57:51 -04:00

56 lines
1.9 KiB
C#

using Bit.Api.Auth.Models.Request.WebAuthn;
using Bit.Core.Auth.Models.Data;
using Bit.Core.Auth.Repositories;
using Bit.Core.Entities;
using Bit.Core.Exceptions;
namespace Bit.Api.KeyManagement.Validators;
public class WebAuthnLoginKeyRotationValidator : IRotationValidator<IEnumerable<WebAuthnLoginRotateKeyRequestModel>, IEnumerable<WebAuthnLoginRotateKeyData>>
{
private readonly IWebAuthnCredentialRepository _webAuthnCredentialRepository;
public WebAuthnLoginKeyRotationValidator(IWebAuthnCredentialRepository webAuthnCredentialRepository)
{
_webAuthnCredentialRepository = webAuthnCredentialRepository;
}
public async Task<IEnumerable<WebAuthnLoginRotateKeyData>> ValidateAsync(User user, IEnumerable<WebAuthnLoginRotateKeyRequestModel> keysToRotate)
{
var result = new List<WebAuthnLoginRotateKeyData>();
var existing = await _webAuthnCredentialRepository.GetManyByUserIdAsync(user.Id);
if (existing == null)
{
return result;
}
var validCredentials = existing.Where(credential => credential.SupportsPrf);
if (!validCredentials.Any())
{
return result;
}
foreach (var ea in validCredentials)
{
var keyToRotate = keysToRotate.FirstOrDefault(c => c.Id == ea.Id);
if (keyToRotate == null)
{
throw new BadRequestException("All existing webauthn prf keys must be included in the rotation.");
}
if (keyToRotate.EncryptedUserKey == null)
{
throw new BadRequestException("WebAuthn prf keys must have user-key during rotation.");
}
if (keyToRotate.EncryptedPublicKey == null)
{
throw new BadRequestException("WebAuthn prf keys must have public-key during rotation.");
}
result.Add(keyToRotate.ToWebAuthnRotateKeyData());
}
return result;
}
}