1
0
mirror of https://github.com/bitwarden/server synced 2026-02-13 23:13:22 +00:00

fix(register): [PM-27084] Account Register Uses New Data Types - Fixed some tests up.

This commit is contained in:
Patrick Pimentel
2025-12-29 13:20:58 -05:00
parent fac1d4bdc2
commit 2d9786e09d
10 changed files with 123 additions and 119 deletions

View File

@@ -1,7 +1,5 @@
#nullable enable
using System.ComponentModel.DataAnnotations;
using Bit.Api.KeyManagement.Models.Requests;
using System.ComponentModel.DataAnnotations;
using Bit.Core.KeyManagement.Models.Api.Request;
namespace Bit.Api.Auth.Models.Request.Accounts;

View File

@@ -1,22 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Api.KeyManagement.Models.Requests;
public class MasterPasswordUnlockDataRequestModel
{
public required KdfRequestModel Kdf { get; init; }
[EncryptedString] public required string MasterKeyWrappedUserKey { get; init; }
[StringLength(256)] public required string Salt { get; init; }
public MasterPasswordUnlockData ToData()
{
return new MasterPasswordUnlockData
{
Kdf = Kdf.ToData(),
MasterKeyWrappedUserKey = MasterKeyWrappedUserKey,
Salt = Salt
};
}
}

View File

@@ -1,6 +1,6 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.KeyManagement.Models.Api.Request;
using Bit.Core.Utilities;
namespace Bit.Core.Auth.Models.Api.Request.Accounts;
@@ -21,8 +21,8 @@ public class RegisterFinishRequestModel : IValidatableObject
public required string Email { get; set; }
public string? EmailVerificationToken { get; set; }
public MasterPasswordAuthenticationData? MasterPasswordAuthentication { get; set; }
public MasterPasswordUnlockData? MasterPasswordUnlock { get; set; }
public MasterPasswordAuthenticationDataRequestModel? MasterPasswordAuthentication { get; set; }
public MasterPasswordUnlockDataRequestModel? MasterPasswordUnlock { get; set; }
// PM-28143 - Remove property below (made optional during migration to MasterPasswordUnlockData)
[StringLength(1000)]
@@ -66,10 +66,10 @@ 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(MasterPasswordAuthentication, MasterPasswordUnlock);
MasterPasswordUnlockDataRequestModel.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthentication, MasterPasswordUnlock);
// PM-28143 - Remove line below
MasterPasswordAuthenticationData.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
MasterPasswordAuthenticationDataRequestModel.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
var user = new User
{
@@ -122,10 +122,10 @@ public class RegisterFinishRequestModel : IValidatableObject
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// PM-28143 - Remove line below
MasterPasswordUnlockData.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthentication, MasterPasswordUnlock);
MasterPasswordUnlockDataRequestModel.ThrowIfExistsAndNotMatchingAuthenticationData(MasterPasswordAuthentication, MasterPasswordUnlock);
// PM-28143 - Remove line below
MasterPasswordAuthenticationData.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
MasterPasswordAuthenticationDataRequestModel.ThrowIfExistsAndHashIsNotEqual(MasterPasswordAuthentication, MasterPasswordHash);
// PM-28143 - Remove line below
var kdf = MasterPasswordUnlock?.Kdf.KdfType

View File

@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.KeyManagement.Models.Data;
namespace Bit.Api.KeyManagement.Models.Requests;
namespace Bit.Core.KeyManagement.Models.Api.Request;
public class MasterPasswordAuthenticationDataRequestModel
{
@@ -18,4 +18,17 @@ public class MasterPasswordAuthenticationDataRequestModel
Salt = Salt
};
}
public static void ThrowIfExistsAndHashIsNotEqual(
MasterPasswordAuthenticationDataRequestModel? authenticationData,
string? hash)
{
if (authenticationData != null && hash != null)
{
if (authenticationData.MasterPasswordAuthenticationHash != hash)
{
throw new Exception("Master password hash and hash are not equal.");
}
}
}
}

View File

@@ -0,0 +1,49 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.Utilities;
namespace Bit.Core.KeyManagement.Models.Api.Request;
public class MasterPasswordUnlockDataRequestModel
{
public required KdfRequestModel Kdf { get; init; }
[EncryptedString] public required string MasterKeyWrappedUserKey { get; init; }
[StringLength(256)] public required string Salt { get; init; }
public MasterPasswordUnlockData ToData()
{
return new MasterPasswordUnlockData
{
Kdf = Kdf.ToData(),
MasterKeyWrappedUserKey = MasterKeyWrappedUserKey,
Salt = Salt
};
}
public static void ThrowIfExistsAndNotMatchingAuthenticationData(
MasterPasswordAuthenticationDataRequestModel? authenticationData,
MasterPasswordUnlockDataRequestModel? unlockData)
{
if (unlockData != null && authenticationData != null)
{
var matches = MatchesAuthenticationData(
unlockData,
authenticationData);
if (!matches)
{
throw new Exception("KDF settings and salt must match between authentication and unlock data.");
}
}
}
private static bool MatchesAuthenticationData(
MasterPasswordUnlockDataRequestModel unlockData,
MasterPasswordAuthenticationDataRequestModel authenticationData)
{
var kdfMatches = unlockData.Kdf.Equals(authenticationData.Kdf);
var saltMatches = unlockData.Salt == authenticationData.Salt;
return kdfMatches && saltMatches;
}
}

View File

@@ -1,8 +1,7 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
using Bit.Core.KeyManagement.Models.Data;
namespace Bit.Api.KeyManagement.Models.Requests;
namespace Bit.Core.KeyManagement.Models.Data;
public class KdfRequestModel
{

View File

@@ -3,6 +3,12 @@ using Bit.Core.Exceptions;
namespace Bit.Core.KeyManagement.Models.Data;
/// <summary>
/// The data used for authentication of a master password.
///
/// This data model does not have any validation, consider using MasterPasswordAuthenticationDataRequestModel
/// if validation is required.
/// </summary>
public class MasterPasswordAuthenticationData
{
public required KdfSettings Kdf { get; init; }
@@ -16,17 +22,4 @@ public class MasterPasswordAuthenticationData
throw new BadRequestException("Invalid master password salt.");
}
}
public static void ThrowIfExistsAndHashIsNotEqual(
MasterPasswordAuthenticationData? authenticationData,
string? hash)
{
if (authenticationData != null && hash != null)
{
if (authenticationData.MasterPasswordAuthenticationHash != hash)
{
throw new Exception("Master password hash and hash are not equal.");
}
}
}
}

View File

@@ -16,31 +16,4 @@ public class MasterPasswordUnlockData
throw new BadRequestException("Invalid master password salt.");
}
}
public static void ThrowIfExistsAndNotMatchingAuthenticationData(
MasterPasswordAuthenticationData? authenticationData,
MasterPasswordUnlockData? unlockData)
{
if (unlockData != null && authenticationData != null)
{
var matches = MatchesAuthenticationData(
unlockData,
authenticationData);
if (!matches)
{
throw new Exception("KDF settings and salt must match between authentication and unlock data.");
}
}
}
private static bool MatchesAuthenticationData(
MasterPasswordUnlockData unlockData,
MasterPasswordAuthenticationData authenticationData)
{
var kdfMatches = unlockData.Kdf.Equals(authenticationData.Kdf);
var saltMatches = unlockData.Salt == authenticationData.Salt;
return kdfMatches && saltMatches;
}
}