mirror of
https://github.com/bitwarden/server.git
synced 2025-05-27 22:34:54 -05:00
Update opaque login with password and update cipherconfig model
This commit is contained in:
parent
0b34f09fc7
commit
d617004435
@ -15,6 +15,7 @@ using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Auth.UserFeatures.TdeOffboardingPassword.Interfaces;
|
||||
using Bit.Core.Auth.UserFeatures.UserMasterPassword.Interfaces;
|
||||
using Bit.Core.Entities;
|
||||
@ -57,6 +58,7 @@ public class AccountsController : Controller
|
||||
_organizationUserValidator;
|
||||
private readonly IRotationValidator<IEnumerable<WebAuthnLoginRotateKeyRequestModel>, IEnumerable<WebAuthnLoginRotateKeyData>>
|
||||
_webauthnKeyValidator;
|
||||
private readonly IOpaqueKeyExchangeService _opaqueKeyExchangeService;
|
||||
|
||||
|
||||
public AccountsController(
|
||||
@ -76,7 +78,8 @@ public class AccountsController : Controller
|
||||
emergencyAccessValidator,
|
||||
IRotationValidator<IEnumerable<ResetPasswordWithOrgIdRequestModel>, IReadOnlyList<OrganizationUser>>
|
||||
organizationUserValidator,
|
||||
IRotationValidator<IEnumerable<WebAuthnLoginRotateKeyRequestModel>, IEnumerable<WebAuthnLoginRotateKeyData>> webAuthnKeyValidator
|
||||
IRotationValidator<IEnumerable<WebAuthnLoginRotateKeyRequestModel>, IEnumerable<WebAuthnLoginRotateKeyData>> webAuthnKeyValidator,
|
||||
IOpaqueKeyExchangeService opaqueKeyExchangeService
|
||||
)
|
||||
{
|
||||
_organizationService = organizationService;
|
||||
@ -94,6 +97,7 @@ public class AccountsController : Controller
|
||||
_emergencyAccessValidator = emergencyAccessValidator;
|
||||
_organizationUserValidator = organizationUserValidator;
|
||||
_webauthnKeyValidator = webAuthnKeyValidator;
|
||||
_opaqueKeyExchangeService = opaqueKeyExchangeService;
|
||||
}
|
||||
|
||||
|
||||
@ -209,8 +213,14 @@ public class AccountsController : Controller
|
||||
throw new UnauthorizedAccessException();
|
||||
}
|
||||
|
||||
Guid? sessionId = null;
|
||||
if (model.OpaqueSessionId != null)
|
||||
{
|
||||
sessionId = Guid.Parse(model.OpaqueSessionId);
|
||||
}
|
||||
|
||||
var result = await _userService.ChangePasswordAsync(user, model.MasterPasswordHash,
|
||||
model.NewMasterPasswordHash, model.MasterPasswordHint, model.Key);
|
||||
model.NewMasterPasswordHash, model.MasterPasswordHint, model.Key, sessionId);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return;
|
||||
|
@ -27,7 +27,7 @@ public class OpaqueKeyExchangeController : Controller
|
||||
public async Task<OpaqueRegistrationStartResponse> StartRegistrationAsync([FromBody] OpaqueRegistrationStartRequest request)
|
||||
{
|
||||
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||
var result = await _opaqueKeyExchangeService.StartRegistration(Convert.FromBase64String(request.RegistrationRequest), user, request.CipherConfiguration);
|
||||
var result = await _opaqueKeyExchangeService.StartRegistration(Convert.FromBase64String(request.RegistrationRequest), user, request.CipherConfiguration.ToNativeConfiguration());
|
||||
return new OpaqueRegistrationStartResponse(result.Item1, Convert.ToBase64String(result.Item2));
|
||||
}
|
||||
|
||||
|
@ -11,4 +11,5 @@ public class PasswordRequestModel : SecretVerificationRequestModel
|
||||
public string MasterPasswordHint { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
public string OpaqueSessionId { get; set; }
|
||||
}
|
||||
|
@ -1,12 +1,50 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bitwarden.OPAQUE;
|
||||
|
||||
namespace Bit.Api.Auth.Models.Request.Opaque;
|
||||
|
||||
|
||||
public class OpaqueRegistrationStartRequest
|
||||
{
|
||||
[Required]
|
||||
public String RegistrationRequest { get; set; }
|
||||
public string RegistrationRequest { get; set; }
|
||||
[Required]
|
||||
public CipherConfiguration CipherConfiguration { get; set; }
|
||||
}
|
||||
|
||||
public class CipherConfiguration
|
||||
{
|
||||
static string OpaqueKe3Ristretto3DHArgonSuite = "OPAQUE_3_RISTRETTO255_OPRF_RISTRETTO255_KEGROUP_3DH_KEX_ARGON2ID13_KSF";
|
||||
|
||||
[Required]
|
||||
public string CipherSuite { get; set; }
|
||||
public Argon2KsfParameters Argon2Parameters { get; set; }
|
||||
|
||||
public Bitwarden.OPAQUE.CipherConfiguration ToNativeConfiguration()
|
||||
{
|
||||
if (CipherSuite == OpaqueKe3Ristretto3DHArgonSuite)
|
||||
{
|
||||
return new Bitwarden.OPAQUE.CipherConfiguration
|
||||
{
|
||||
OprfCS = Bitwarden.OPAQUE.OprfCS.Ristretto255,
|
||||
KeGroup = Bitwarden.OPAQUE.KeGroup.Ristretto255,
|
||||
KeyExchange = Bitwarden.OPAQUE.KeyExchange.TripleDH,
|
||||
KSF = new Bitwarden.OPAQUE.Argon2id(Argon2Parameters.iterations, Argon2Parameters.memory, Argon2Parameters.parallelism)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unsupported cipher suite");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Argon2KsfParameters
|
||||
{
|
||||
// Memory in KiB
|
||||
[Required]
|
||||
public int memory;
|
||||
[Required]
|
||||
public int iterations;
|
||||
[Required]
|
||||
public int parallelism;
|
||||
}
|
||||
|
@ -37,9 +37,6 @@ public class OpaqueKeyExchangeService : IOpaqueKeyExchangeService
|
||||
{
|
||||
var registrationFinish = _bitwardenOpaque.FinishRegistration(cipherConfiguration, registrationUpload);
|
||||
SessionStore.RegisterSessions[sessionId].serverRegistration = registrationFinish.serverRegistration;
|
||||
|
||||
// todo move to changepassword
|
||||
SetActive(sessionId, user);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public interface IUserService
|
||||
Task InitiateEmailChangeAsync(User user, string newEmail);
|
||||
Task<IdentityResult> ChangeEmailAsync(User user, string masterPassword, string newEmail, string newMasterPassword,
|
||||
string token, string key);
|
||||
Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword, string passwordHint, string key);
|
||||
Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword, string passwordHint, string key, Guid? opaqueSessionId);
|
||||
Task<IdentityResult> SetKeyConnectorKeyAsync(User user, string key, string orgIdentifier);
|
||||
Task<IdentityResult> ConvertToKeyConnectorAsync(User user);
|
||||
Task<IdentityResult> AdminResetPasswordAsync(OrganizationUserType type, Guid orgId, Guid id, string newMasterPassword, string key);
|
||||
|
@ -11,6 +11,7 @@ using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Models.Sales;
|
||||
using Bit.Core.Billing.Services;
|
||||
@ -78,6 +79,7 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
|
||||
private readonly IRevokeNonCompliantOrganizationUserCommand _revokeNonCompliantOrganizationUserCommand;
|
||||
private readonly IDistributedCache _distributedCache;
|
||||
private readonly IOpaqueKeyExchangeService _opaqueKeyExchangeService;
|
||||
|
||||
public UserService(
|
||||
IUserRepository userRepository,
|
||||
@ -115,7 +117,8 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
IPremiumUserBillingService premiumUserBillingService,
|
||||
IRemoveOrganizationUserCommand removeOrganizationUserCommand,
|
||||
IRevokeNonCompliantOrganizationUserCommand revokeNonCompliantOrganizationUserCommand,
|
||||
IDistributedCache distributedCache)
|
||||
IDistributedCache distributedCache,
|
||||
IOpaqueKeyExchangeService opaqueKeyExchangeService)
|
||||
: base(
|
||||
store,
|
||||
optionsAccessor,
|
||||
@ -159,6 +162,7 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
_removeOrganizationUserCommand = removeOrganizationUserCommand;
|
||||
_revokeNonCompliantOrganizationUserCommand = revokeNonCompliantOrganizationUserCommand;
|
||||
_distributedCache = distributedCache;
|
||||
_opaqueKeyExchangeService = opaqueKeyExchangeService;
|
||||
}
|
||||
|
||||
public Guid? GetProperUserId(ClaimsPrincipal principal)
|
||||
@ -643,7 +647,7 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
}
|
||||
|
||||
public async Task<IdentityResult> ChangePasswordAsync(User user, string masterPassword, string newMasterPassword, string passwordHint,
|
||||
string key)
|
||||
string key, Guid? opaqueSessionId)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@ -664,6 +668,14 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
user.Key = key;
|
||||
user.MasterPasswordHint = passwordHint;
|
||||
|
||||
if (opaqueSessionId != null)
|
||||
{
|
||||
_opaqueKeyExchangeService.SetActive((Guid)opaqueSessionId, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
_opaqueKeyExchangeService.Unenroll(user);
|
||||
}
|
||||
await _userRepository.ReplaceAsync(user);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_ChangedPassword);
|
||||
await _pushService.PushLogOutAsync(user.Id, true);
|
||||
@ -804,6 +816,8 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
user.ForcePasswordReset = true;
|
||||
user.Key = key;
|
||||
|
||||
// TODO: Add support
|
||||
_opaqueKeyExchangeService.Unenroll(user);
|
||||
await _userRepository.ReplaceAsync(user);
|
||||
await _mailService.SendAdminResetPasswordEmailAsync(user.Email, user.Name, org.DisplayName());
|
||||
await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_AdminResetPassword);
|
||||
@ -830,6 +844,8 @@ public class UserService : UserManager<User>, IUserService, IDisposable
|
||||
user.Key = key;
|
||||
user.MasterPasswordHint = hint;
|
||||
|
||||
// TODO: Add support
|
||||
_opaqueKeyExchangeService.Unenroll(user);
|
||||
await _userRepository.ReplaceAsync(user);
|
||||
await _mailService.SendUpdatedTempPasswordEmailAsync(user.Email, user.Name);
|
||||
await _eventService.LogUserEventAsync(user.Id, EventType.User_UpdatedTempPassword);
|
||||
|
Loading…
x
Reference in New Issue
Block a user