mirror of
https://github.com/bitwarden/server.git
synced 2025-07-05 18:12:48 -05:00
[PM-4371] Implement PRF key rotation (#4157)
* Send rotateable keyset on list webauthn keys * Implement basic prf key rotation * Add validator for webauthn rotation * Fix accounts controller tests * Add webauthn rotation validator tests * Introduce separate request model * Fix tests * Remove extra empty line * Remove filtering in validator * Don't send encrypted private key * Fix tests * Implement delegated webauthn db transactions * Add backward compatibility * Fix query not working * Update migration sql * Update dapper query * Remove unused helper * Rename webauthn to WebAuthnLogin * Fix linter errors * Fix tests * Fix tests
This commit is contained in:
@ -15,4 +15,5 @@ public class RotateUserKeyData
|
||||
public IReadOnlyList<Send> Sends { get; set; }
|
||||
public IEnumerable<EmergencyAccess> EmergencyAccesses { get; set; }
|
||||
public IReadOnlyList<OrganizationUser> OrganizationUsers { get; set; }
|
||||
public IEnumerable<WebAuthnLoginRotateKeyData> WebAuthnKeys { get; set; }
|
||||
}
|
||||
|
21
src/Core/Auth/Models/Data/WebAuthnLoginRotateKeyData.cs
Normal file
21
src/Core/Auth/Models/Data/WebAuthnLoginRotateKeyData.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Auth.Models.Data;
|
||||
|
||||
public class WebAuthnLoginRotateKeyData
|
||||
{
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(2000)]
|
||||
public string EncryptedUserKey { get; set; }
|
||||
|
||||
[Required]
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(2000)]
|
||||
public string EncryptedPublicKey { get; set; }
|
||||
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.UserFeatures.UserKey;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
namespace Bit.Core.Auth.Repositories;
|
||||
@ -8,4 +10,5 @@ public interface IWebAuthnCredentialRepository : IRepository<WebAuthnCredential,
|
||||
Task<WebAuthnCredential> GetByIdAsync(Guid id, Guid userId);
|
||||
Task<ICollection<WebAuthnCredential>> GetManyByUserIdAsync(Guid userId);
|
||||
Task<bool> UpdateAsync(WebAuthnCredential credential);
|
||||
UpdateEncryptedDataForKeyRotation UpdateKeysForRotationAsync(Guid userId, IEnumerable<WebAuthnLoginRotateKeyData> credentials);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
@ -20,6 +21,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IPushNotificationService _pushService;
|
||||
private readonly IdentityErrorDescriber _identityErrorDescriber;
|
||||
private readonly IWebAuthnCredentialRepository _credentialRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="RotateUserKeyCommand"/>
|
||||
@ -35,7 +37,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
|
||||
public RotateUserKeyCommand(IUserService userService, IUserRepository userRepository,
|
||||
ICipherRepository cipherRepository, IFolderRepository folderRepository, ISendRepository sendRepository,
|
||||
IEmergencyAccessRepository emergencyAccessRepository, IOrganizationUserRepository organizationUserRepository,
|
||||
IPushNotificationService pushService, IdentityErrorDescriber errors)
|
||||
IPushNotificationService pushService, IdentityErrorDescriber errors, IWebAuthnCredentialRepository credentialRepository)
|
||||
{
|
||||
_userService = userService;
|
||||
_userRepository = userRepository;
|
||||
@ -46,6 +48,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_pushService = pushService;
|
||||
_identityErrorDescriber = errors;
|
||||
_credentialRepository = credentialRepository;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -68,7 +71,7 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
|
||||
user.Key = model.Key;
|
||||
user.PrivateKey = model.PrivateKey;
|
||||
if (model.Ciphers.Any() || model.Folders.Any() || model.Sends.Any() || model.EmergencyAccesses.Any() ||
|
||||
model.OrganizationUsers.Any())
|
||||
model.OrganizationUsers.Any() || model.WebAuthnKeys.Any())
|
||||
{
|
||||
List<UpdateEncryptedDataForKeyRotation> saveEncryptedDataActions = new();
|
||||
|
||||
@ -99,6 +102,11 @@ public class RotateUserKeyCommand : IRotateUserKeyCommand
|
||||
_organizationUserRepository.UpdateForKeyRotation(user.Id, model.OrganizationUsers));
|
||||
}
|
||||
|
||||
if (model.WebAuthnKeys.Any())
|
||||
{
|
||||
saveEncryptedDataActions.Add(_credentialRepository.UpdateKeysForRotationAsync(user.Id, model.WebAuthnKeys));
|
||||
}
|
||||
|
||||
await _userRepository.UpdateUserKeyAndEncryptedDataAsync(user, saveEncryptedDataActions);
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user