mirror of
https://github.com/bitwarden/server
synced 2026-01-29 07:43:22 +00:00
fix(register): [PM-27084] Account Register Uses New Data Types - Added new checks for master password authentication data.
This commit is contained in:
@@ -22,7 +22,7 @@ public class RegisterFinishRequestModel : IValidatableObject
|
||||
public string? EmailVerificationToken { get; set; }
|
||||
|
||||
public MasterPasswordAuthenticationData? MasterPasswordAuthentication { get; set; }
|
||||
public MasterPasswordUnlockData? MasterPasswordUnlockData { get; set; }
|
||||
public MasterPasswordUnlockData? MasterPasswordUnlock { get; set; }
|
||||
|
||||
// PM-28143 - Remove property below (made optional during migration to MasterPasswordUnlockData)
|
||||
[StringLength(1000)]
|
||||
@@ -66,25 +66,25 @@ public class RegisterFinishRequestModel : IValidatableObject
|
||||
// PM-28143 - Remove line below
|
||||
// When we process this request to a user object, check if the unlock and authentication
|
||||
// data has been passed through, and if so they should have matching values.
|
||||
MasterPasswordUnlockData.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthenticationData, MasterPasswordUnlockData);
|
||||
MasterPasswordUnlockData.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthentication, MasterPasswordUnlock);
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
MasterPasswordAuthenticationData.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthenticationData, MasterPasswordHash);
|
||||
MasterPasswordAuthenticationData.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
|
||||
|
||||
var user = new User
|
||||
{
|
||||
Email = Email,
|
||||
MasterPasswordHint = MasterPasswordHint,
|
||||
Kdf = MasterPasswordUnlockData?.Kdf.KdfType ?? Kdf
|
||||
Kdf = MasterPasswordUnlock?.Kdf.KdfType ?? Kdf
|
||||
?? throw new Exception("KdfType couldn't be found on either the MasterPasswordUnlockData or the Kdf property passed in."),
|
||||
KdfIterations = MasterPasswordUnlockData?.Kdf.Iterations ?? KdfIterations
|
||||
KdfIterations = MasterPasswordUnlock?.Kdf.Iterations ?? KdfIterations
|
||||
?? throw new Exception("KdfIterations couldn't be found on either the MasterPasswordUnlockData or the KdfIterations property passed in."),
|
||||
// KdfMemory and KdfParallelism are optional (only used for Argon2id)
|
||||
KdfMemory = MasterPasswordUnlockData?.Kdf.Memory ?? KdfMemory,
|
||||
KdfParallelism = MasterPasswordUnlockData?.Kdf.Parallelism ?? KdfParallelism,
|
||||
KdfMemory = MasterPasswordUnlock?.Kdf.Memory ?? KdfMemory,
|
||||
KdfParallelism = MasterPasswordUnlock?.Kdf.Parallelism ?? KdfParallelism,
|
||||
// PM-28827 To be added when MasterPasswordSalt is added to the user column
|
||||
// MasterPasswordSalt = MasterPasswordUnlockData?.Salt ?? Email.ToLower().Trim(),
|
||||
Key = MasterPasswordUnlockData?.MasterKeyWrappedUserKey ?? UserSymmetricKey ?? throw new Exception("MasterKeyWrappedUserKey couldn't be found on either the MasterPasswordUnlockData or the UserSymmetricKey property passed in."),
|
||||
Key = MasterPasswordUnlock?.MasterKeyWrappedUserKey ?? UserSymmetricKey ?? throw new Exception("MasterKeyWrappedUserKey couldn't be found on either the MasterPasswordUnlockData or the UserSymmetricKey property passed in."),
|
||||
};
|
||||
|
||||
UserAsymmetricKeys.ToUser(user);
|
||||
@@ -121,24 +121,28 @@ public class RegisterFinishRequestModel : IValidatableObject
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
MasterPasswordUnlockData.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthenticationData, MasterPasswordUnlockData);
|
||||
// PM-28143 - Remove line below
|
||||
MasterPasswordUnlockData.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthentication, MasterPasswordUnlock);
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
var kdf = MasterPasswordUnlockData?.Kdf.KdfType
|
||||
MasterPasswordAuthenticationData.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
var kdf = MasterPasswordUnlock?.Kdf.KdfType
|
||||
?? Kdf
|
||||
?? throw new Exception($"{nameof(Kdf)} not found on RequestModel");
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
var kdfIterations = MasterPasswordUnlockData?.Kdf.Iterations
|
||||
var kdfIterations = MasterPasswordUnlock?.Kdf.Iterations
|
||||
?? KdfIterations
|
||||
?? throw new Exception($"{nameof(KdfIterations)} not found on RequestModel");
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
var kdfMemory = MasterPasswordUnlockData?.Kdf.Memory
|
||||
var kdfMemory = MasterPasswordUnlock?.Kdf.Memory
|
||||
?? KdfMemory;
|
||||
|
||||
// PM-28143 - Remove line below
|
||||
var kdfParallelism = MasterPasswordUnlockData?.Kdf.Parallelism
|
||||
var kdfParallelism = MasterPasswordUnlock?.Kdf.Parallelism
|
||||
?? KdfParallelism;
|
||||
|
||||
// PM-28143 - Remove line below in favor of using the unlock data.
|
||||
|
||||
@@ -156,7 +156,7 @@ public class AccountsController : Controller
|
||||
IdentityResult? identityResult = null;
|
||||
|
||||
// PM-28143 - Just use the MasterPasswordAuthenticationData.MasterPasswordAuthenticationHash
|
||||
string masterPasswordHash = model.MasterPasswordAuthenticationData?.MasterPasswordAuthenticationHash
|
||||
string masterPasswordHash = model.MasterPasswordAuthentication?.MasterPasswordAuthenticationHash
|
||||
?? model.MasterPasswordHash ?? throw new BadRequestException("MasterPasswordHash couldn't be found on either the MasterPasswordAuthenticationData or the MasterPasswordHash property passed in.");
|
||||
|
||||
switch (model.GetTokenType())
|
||||
|
||||
@@ -607,7 +607,7 @@ public class AccountsControllerTests : IDisposable
|
||||
{
|
||||
Email = email,
|
||||
EmailVerificationToken = emailVerificationToken,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = new KdfSettings
|
||||
{
|
||||
@@ -619,7 +619,7 @@ public class AccountsControllerTests : IDisposable
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email // salt choice is not validated here during registration
|
||||
},
|
||||
MasterPasswordUnlockData = new MasterPasswordUnlockData
|
||||
MasterPasswordUnlock = new MasterPasswordUnlockData
|
||||
{
|
||||
Kdf = new KdfSettings
|
||||
{
|
||||
@@ -725,7 +725,7 @@ public class AccountsControllerTests : IDisposable
|
||||
Email = email,
|
||||
OrgInviteToken = orgInviteToken,
|
||||
OrganizationUserId = organizationUserId,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = new KdfSettings
|
||||
{
|
||||
@@ -735,7 +735,7 @@ public class AccountsControllerTests : IDisposable
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email
|
||||
},
|
||||
MasterPasswordUnlockData = new MasterPasswordUnlockData
|
||||
MasterPasswordUnlock = new MasterPasswordUnlockData
|
||||
{
|
||||
Kdf = new KdfSettings
|
||||
{
|
||||
@@ -842,14 +842,14 @@ public class AccountsControllerTests : IDisposable
|
||||
{
|
||||
Email = email,
|
||||
EmailVerificationToken = emailVerificationToken,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
// present but not used by ToUser for KDF/Key
|
||||
Kdf = new KdfSettings { KdfType = KdfType.Argon2id, Iterations = iterations },
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email
|
||||
},
|
||||
MasterPasswordUnlockData = new MasterPasswordUnlockData
|
||||
MasterPasswordUnlock = new MasterPasswordUnlockData
|
||||
{
|
||||
Kdf = unlockKdf,
|
||||
MasterKeyWrappedUserKey = masterKeyWrappedUserKey,
|
||||
@@ -901,7 +901,7 @@ public class AccountsControllerTests : IDisposable
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
UserSymmetricKey = legacyKey,
|
||||
MasterPasswordUnlockData = null,
|
||||
MasterPasswordUnlock = null,
|
||||
UserAsymmetricKeys = new KeysRequestModel
|
||||
{
|
||||
PublicKey = publicKey,
|
||||
@@ -942,14 +942,14 @@ public class AccountsControllerTests : IDisposable
|
||||
{
|
||||
Email = email,
|
||||
EmailVerificationToken = emailVerificationToken,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
// present but ToUser does not source KDF from here
|
||||
Kdf = new KdfSettings { KdfType = KdfType.Argon2id, Iterations = iterations },
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email
|
||||
},
|
||||
MasterPasswordUnlockData = null,
|
||||
MasterPasswordUnlock = null,
|
||||
Kdf = null,
|
||||
KdfIterations = iterations,
|
||||
UserSymmetricKey = masterKeyWrappedUserKey,
|
||||
@@ -980,14 +980,14 @@ public class AccountsControllerTests : IDisposable
|
||||
{
|
||||
Email = email,
|
||||
EmailVerificationToken = emailVerificationToken,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
// present but ToUser does not source iterations from here
|
||||
Kdf = new KdfSettings { KdfType = kdfType, Iterations = AuthConstants.PBKDF2_ITERATIONS.Default },
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email
|
||||
},
|
||||
MasterPasswordUnlockData = null,
|
||||
MasterPasswordUnlock = null,
|
||||
Kdf = kdfType,
|
||||
KdfIterations = null,
|
||||
UserSymmetricKey = masterKeyWrappedUserKey,
|
||||
@@ -1018,13 +1018,13 @@ public class AccountsControllerTests : IDisposable
|
||||
{
|
||||
Email = email,
|
||||
EmailVerificationToken = emailVerificationToken,
|
||||
MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = new KdfSettings { KdfType = kdfType, Iterations = iterations },
|
||||
MasterPasswordAuthenticationHash = masterPasswordHash,
|
||||
Salt = email
|
||||
},
|
||||
MasterPasswordUnlockData = null,
|
||||
MasterPasswordUnlock = null,
|
||||
Kdf = kdfType,
|
||||
KdfIterations = iterations,
|
||||
UserSymmetricKey = null,
|
||||
|
||||
@@ -206,7 +206,7 @@ public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
|
||||
requestModel.KdfIterations ??= AuthConstants.PBKDF2_ITERATIONS.Default;
|
||||
// Ensure a symmetric key is provided when no unlock data is present
|
||||
// PM-28143 - When MasterPasswordUnlockData is required, delete the UserSymmetricKey fallback block below.
|
||||
if (requestModel.MasterPasswordUnlockData == null && string.IsNullOrWhiteSpace(requestModel.UserSymmetricKey))
|
||||
if (requestModel.MasterPasswordUnlock == null && string.IsNullOrWhiteSpace(requestModel.UserSymmetricKey))
|
||||
{
|
||||
requestModel.UserSymmetricKey = "user_symmetric_key";
|
||||
}
|
||||
@@ -234,14 +234,14 @@ public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
|
||||
Parallelism = effectiveParallelism
|
||||
};
|
||||
|
||||
if (requestModel.MasterPasswordUnlockData != null)
|
||||
if (requestModel.MasterPasswordUnlock != null)
|
||||
{
|
||||
var unlock = requestModel.MasterPasswordUnlockData;
|
||||
var unlock = requestModel.MasterPasswordUnlock;
|
||||
// PM-28143 - Once UserSymmetricKey is removed and UnlockData is required, delete the fallback to UserSymmetricKey below.
|
||||
var masterKeyWrappedUserKey = !string.IsNullOrWhiteSpace(unlock.MasterKeyWrappedUserKey)
|
||||
? unlock.MasterKeyWrappedUserKey
|
||||
: (string.IsNullOrWhiteSpace(requestModel.UserSymmetricKey) ? "user_symmetric_key" : requestModel.UserSymmetricKey);
|
||||
requestModel.MasterPasswordUnlockData = new MasterPasswordUnlockData
|
||||
requestModel.MasterPasswordUnlock = new MasterPasswordUnlockData
|
||||
{
|
||||
Kdf = alignedKdf,
|
||||
MasterKeyWrappedUserKey = masterKeyWrappedUserKey,
|
||||
@@ -249,12 +249,12 @@ public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
|
||||
};
|
||||
}
|
||||
|
||||
if (requestModel.MasterPasswordAuthenticationData != null)
|
||||
if (requestModel.MasterPasswordAuthentication != null)
|
||||
{
|
||||
// Ensure registration uses the same hash the tests will provide at login.
|
||||
// PM-28143 - When MasterPasswordAuthenticationData is the only source of the auth hash,
|
||||
// stop overriding it from MasterPasswordHash and delete this whole reassignment block.
|
||||
requestModel.MasterPasswordAuthenticationData = new MasterPasswordAuthenticationData
|
||||
requestModel.MasterPasswordAuthentication = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = alignedKdf,
|
||||
MasterPasswordAuthenticationHash = requestModel.MasterPasswordHash,
|
||||
|
||||
Reference in New Issue
Block a user