1
0
mirror of https://github.com/bitwarden/server synced 2026-01-31 00:33:17 +00:00

test(register): [PM-27084] Account Register Uses New Data Types - Addressed feedback and added tests.

This commit is contained in:
Patrick Pimentel
2026-01-12 15:11:58 -05:00
parent 9e43ca2442
commit 93c9631a75
4 changed files with 24 additions and 13 deletions

View File

@@ -125,6 +125,12 @@ public class RegisterFinishRequestModel : IValidatableObject
$"{nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash)} and root level {nameof(MasterPasswordHash)} provided and are not equal. Only provide one.",
[nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash), nameof(MasterPasswordHash)]);
}
} // 1.5 if there is no master password hash that is unacceptable even though they are both optional in the model
else if (MasterPasswordAuthentication == null && MasterPasswordHash == null)
{
yield return new ValidationResult(
$"{nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash)} and {nameof(MasterPasswordHash)} not found on request, one needs to be defined.",
[nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash), nameof(MasterPasswordHash)]);
}
// 2. Validate kdf settings.

View File

@@ -147,22 +147,22 @@ public class AccountsController : Controller
IdentityResult? identityResult = null;
// PM-28143 - Just use the 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.");
string masterPasswordAuthenticationHash = model.MasterPasswordAuthentication?.MasterPasswordAuthenticationHash
?? model.MasterPasswordHash!;
switch (model.GetTokenType())
{
case RegisterFinishTokenType.EmailVerification:
identityResult = await _registerUserCommand.RegisterUserViaEmailVerificationToken(
user,
masterPasswordHash,
masterPasswordAuthenticationHash,
model.EmailVerificationToken!);
return ProcessRegistrationResult(identityResult, user);
case RegisterFinishTokenType.OrganizationInvite:
identityResult = await _registerUserCommand.RegisterUserViaOrganizationInviteToken(
user,
masterPasswordHash,
masterPasswordAuthenticationHash,
model.OrgInviteToken!,
model.OrganizationUserId);
return ProcessRegistrationResult(identityResult, user);
@@ -170,14 +170,14 @@ public class AccountsController : Controller
case RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan:
identityResult = await _registerUserCommand.RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(
user,
masterPasswordHash,
masterPasswordAuthenticationHash,
model.OrgSponsoredFreeFamilyPlanToken!);
return ProcessRegistrationResult(identityResult, user);
case RegisterFinishTokenType.EmergencyAccessInvite:
identityResult = await _registerUserCommand.RegisterUserViaAcceptEmergencyAccessInviteToken(
user,
masterPasswordHash,
masterPasswordAuthenticationHash,
model.AcceptEmergencyAccessInviteToken!,
(Guid)model.AcceptEmergencyAccessId!);
return ProcessRegistrationResult(identityResult, user);
@@ -185,7 +185,7 @@ public class AccountsController : Controller
case RegisterFinishTokenType.ProviderInvite:
identityResult = await _registerUserCommand.RegisterUserViaProviderInviteToken(
user,
masterPasswordHash,
masterPasswordAuthenticationHash,
model.ProviderInviteToken!,
(Guid)model.ProviderUserId!);
return ProcessRegistrationResult(identityResult, user);

View File

@@ -275,22 +275,28 @@ public class RegisterFinishRequestModelTests
}
[Fact]
public void Validate_WhenNeitherAuthNorUnlock_AndValidRootKdf_IsValid()
public void Validate_WhenAuthAndRootHashBothMissing_ReturnsMissingHashErrorOnly()
{
var model = new RegisterFinishRequestModel
{
Email = "user@example.com",
UserAsymmetricKeys = new KeysRequestModel { PublicKey = "pk", EncryptedPrivateKey = "sk" },
// Both MasterPasswordAuthentication and MasterPasswordHash are missing
MasterPasswordAuthentication = null,
MasterPasswordHash = null,
// Provide valid root KDF to avoid root KDF errors
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
// Memory and Parallelism irrelevant for PBKDF2
EmailVerificationToken = "token"
EmailVerificationToken = "token" // avoid token error
};
var results = Validate(model);
Assert.DoesNotContain(results, r => r.ErrorMessage?.Contains("Kdf") == true);
Assert.Empty(results.Where(r => r.ErrorMessage == "No valid registration token provided"));
// Only the new missing hash error should be present
Assert.Single(results);
Assert.Equal($"{nameof(MasterPasswordAuthenticationDataRequestModel.MasterPasswordAuthenticationHash)} and {nameof(RegisterFinishRequestModel.MasterPasswordHash)} not found on request, one needs to be defined.", results[0].ErrorMessage);
Assert.Contains(nameof(MasterPasswordAuthenticationDataRequestModel.MasterPasswordAuthenticationHash), results[0].MemberNames);
Assert.Contains(nameof(RegisterFinishRequestModel.MasterPasswordHash), results[0].MemberNames);
}
[Fact]

View File

@@ -239,7 +239,6 @@ public class IdentityApplicationFactory : WebApplicationFactoryBase<Startup>
if (requestModel.MasterPasswordUnlock != null)
{
var unlock = requestModel.MasterPasswordUnlock;
// PM-28143 - Once UserSymmetricKey is removed and UnlockData is required, delete the fallback to UserSymmetricKey below.
// Always force a valid encrypted string for tests to avoid model validation failures.
var masterKeyWrappedUserKey = DefaultEncryptedString;
requestModel.MasterPasswordUnlock = new MasterPasswordUnlockDataRequestModel