Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
6c7daa6
feat(register): [PM-27084] Account Register Uses New Data Types - Iniโ€ฆ
Patrick-Pimentel-Bitwarden Dec 9, 2025
1535fa3
feat(register): [PM-27084] Account Register Uses New Data Types - Fixโ€ฆ
Patrick-Pimentel-Bitwarden Dec 9, 2025
9000474
fix(register): [PM-27084] Account Register Uses New Data Types - Addeโ€ฆ
Patrick-Pimentel-Bitwarden Dec 10, 2025
d7ddf2e
fix(register): [PM-27084] Account Register Uses New Data Types - Accoโ€ฆ
Patrick-Pimentel-Bitwarden Dec 11, 2025
08f3acd
docs(register): [PM-27084] Account Register Uses New Data Types - Madโ€ฆ
Patrick-Pimentel-Bitwarden Dec 11, 2025
f47dac9
test(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Dec 11, 2025
bb2ba14
Update src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequesโ€ฆ
Patrick-Pimentel-Bitwarden Dec 11, 2025
7cb55eb
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-types
Patrick-Pimentel-Bitwarden Dec 11, 2025
b33e1ac
docs(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Dec 11, 2025
c21d7b4
test(register): [PM-27084] Account Register Uses New Data Types - Tesโ€ฆ
Patrick-Pimentel-Bitwarden Dec 16, 2025
aa8e8cc
test(register): [PM-27084] Account Register Uses New Data Types - Fixโ€ฆ
Patrick-Pimentel-Bitwarden Dec 16, 2025
5b2edef
test(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Dec 23, 2025
57f69ad
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-types
Patrick-Pimentel-Bitwarden Dec 23, 2025
4f81d75
Update src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequesโ€ฆ
Patrick-Pimentel-Bitwarden Dec 23, 2025
fac1d4b
fix(register): [PM-27084] Account Register Uses New Data Types - Addeโ€ฆ
Patrick-Pimentel-Bitwarden Dec 29, 2025
2d9786e
fix(register): [PM-27084] Account Register Uses New Data Types - Fixeโ€ฆ
Patrick-Pimentel-Bitwarden Dec 29, 2025
cc895d0
fix(register): [PM-27084] Account Register Uses New Data Types - Addeโ€ฆ
Patrick-Pimentel-Bitwarden Dec 29, 2025
4475649
fix(register): [PM-27084] Account Register Uses New Data Types - Remoโ€ฆ
Patrick-Pimentel-Bitwarden Dec 30, 2025
a705ea4
fix(register): [PM-27084] Account Register Uses New Data Types - Shufโ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
227f3a0
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
fb54d21
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
b0cce70
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
af2f704
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
015d2ed
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
67ff0da
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-types
Patrick-Pimentel-Bitwarden Dec 31, 2025
fc507a4
comment(register): [PM-27084] Account Register Uses New Data Types - โ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
05d8cc5
test(register): [PM-27084] Account Register Uses New Data Types - Fixโ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
e531ab1
test(register): [PM-27084] Account Register Uses New Data Types - Fixโ€ฆ
Patrick-Pimentel-Bitwarden Dec 31, 2025
28640d0
fix(register): [PM-27084] Account Register Uses New Data Types - Addrโ€ฆ
Patrick-Pimentel-Bitwarden Jan 1, 2026
260b289
fix(register): [PM-27084] Account Register Uses New Data Types - Fixeโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
06bf7b8
fix(register): [PM-27084] Account Register Uses New Data Types - Convโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
c255e39
fix(register): [PM-27084] Account Register Uses New Data Types - Addeโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
3aa0e4c
fix(register): [PM-27084] Account Register Uses New Data Types - Shufโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
2111df7
fix(register): [PM-27084] Account Register Uses New Data Types - Remoโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
65c0ac9
fix(register): [PM-27084] Account Register Uses New Data Types - Remoโ€ฆ
Patrick-Pimentel-Bitwarden Jan 2, 2026
a5890d2
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-types
Patrick-Pimentel-Bitwarden Jan 2, 2026
b5dadcd
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-types
Patrick-Pimentel-Bitwarden Jan 5, 2026
9e43ca2
test(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Jan 9, 2026
93c9631
test(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Jan 12, 2026
f73904d
Merge remote-tracking branch 'origin' into auth/pm-27084/register-accโ€ฆ
Patrick-Pimentel-Bitwarden Jan 12, 2026
f92d7d2
test(register): [PM-27084] Account Register Uses New Data Types - Addโ€ฆ
Patrick-Pimentel-Bitwarden Jan 12, 2026
6301dbf
test(register): [PM-27084] Account Register Uses New Data Types - Fixโ€ฆ
Patrick-Pimentel-Bitwarden Jan 15, 2026
01c8171
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-typeโ€ฆ
Patrick-Pimentel-Bitwarden Jan 15, 2026
968692c
Merge remote-tracking branch 'origin' into auth/pm-27084/register-accโ€ฆ
Patrick-Pimentel-Bitwarden Jan 22, 2026
e14f6a4
fix(register): [PM-27084] Account Register Uses New Data Types - Addeโ€ฆ
Patrick-Pimentel-Bitwarden Jan 22, 2026
fb98850
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-typeโ€ฆ
bnagawiecki Feb 2, 2026
d9b53c4
Merge branch 'main' into auth/pm-27084/register-accepts-new-data-typeโ€ฆ
Patrick-Pimentel-Bitwarden Feb 3, 2026
c026649
[PM-27278] add AccountKeysRequestModel to RegisterFinishRequestModel โ€ฆ
eligrubb Dec 17, 2025
a247343
Fixed lint and build errors.
eligrubb Feb 4, 2026
6bcbb69
Merge main into branch
eligrubb Feb 6, 2026
4341d21
Addressing code review comments
eligrubb Feb 6, 2026
16e2a37
Merge branch 'main' into km/pm-27278/register-password-based-account-v2
Thomas-Avery Feb 10, 2026
b4613ac
Fix kdf settings for test and update migration script date
eligrubb Feb 10, 2026
797a787
Merge branch 'main' into km/pm-27278/register-password-based-account-v2
eligrubb Feb 23, 2026
66c3938
Fix date for sql migration script
eligrubb Feb 23, 2026
f7760be
Fix date for sql migration script
eligrubb Mar 5, 2026
cf5893e
Merge 'main' into branch
eligrubb Mar 5, 2026
d733a6f
Merge branch 'main' into branch
eligrubb Mar 6, 2026
eb9bc45
Rename sql procedure
eligrubb Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
๏ปฟusing Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.KeyManagement.Models.Api.Request;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.Utilities;

namespace Bit.Core.Auth.Models.Api.Request.Accounts;
Expand Down Expand Up @@ -38,7 +40,12 @@ public class RegisterFinishRequestModel : IValidatableObject
// in the MasterPasswordAuthenticationData.
public string? UserSymmetricKey { get; set; }

public required KeysRequestModel UserAsymmetricKeys { get; set; }
// TODO Remove property below, deprecated due to new AccountKeys property
// https://bitwarden.atlassian.net/browse/PM-27326
// Will throw error if both UserAsymmetricKeys and AccountKeys do not exist.
public KeysRequestModel? UserAsymmetricKeys { get; set; }

public AccountKeysRequestModel? AccountKeys { get; set; }

// PM-28143 - Remove line below (made optional during migration to MasterPasswordUnlockData)
public KdfType? Kdf { get; set; }
Expand All @@ -61,25 +68,84 @@ public class RegisterFinishRequestModel : IValidatableObject

public Guid? ProviderUserId { get; set; }

public User ToUser()
public User ToUser(bool IsV2Encryption)
{
var user = new User
// TODO remove IsV2Encryption bool and simplify logic below after a compatibility period - once V2 accounts are supported
// https://bitwarden.atlassian.net/browse/PM-27326
if (!IsV2Encryption)
{
var user = new User
{
Email = Email,
MasterPasswordHint = MasterPasswordHint,
Kdf = (KdfType)(MasterPasswordUnlock?.Kdf.KdfType ?? Kdf)!,
KdfIterations = (int)(MasterPasswordUnlock?.Kdf.Iterations ?? KdfIterations)!,
// KdfMemory and KdfParallelism are optional (only used for Argon2id)
KdfMemory = MasterPasswordUnlock?.Kdf.Memory ?? KdfMemory,
KdfParallelism = MasterPasswordUnlock?.Kdf.Parallelism ?? KdfParallelism,
// PM-28827 To be added when MasterPasswordSalt is added to the user column
// MasterPasswordSalt = MasterPasswordUnlock?.Salt ?? Email.ToLower().Trim(),
Key = MasterPasswordUnlock?.MasterKeyWrappedUserKey ?? UserSymmetricKey
};

user = UserAsymmetricKeys?.ToUser(user) ?? throw new Exception("User's public and private account keys couldn't be found in either AccountKeys or UserAsymmetricKeys");

return user;
}
return new User
{
Email = Email,
MasterPasswordHint = MasterPasswordHint,
Kdf = (KdfType)(MasterPasswordUnlock?.Kdf.KdfType ?? Kdf)!,
KdfIterations = (int)(MasterPasswordUnlock?.Kdf.Iterations ?? KdfIterations)!,
// KdfMemory and KdfParallelism are optional (only used for Argon2id)
KdfMemory = MasterPasswordUnlock?.Kdf.Memory ?? KdfMemory,
KdfParallelism = MasterPasswordUnlock?.Kdf.Parallelism ?? KdfParallelism,
// PM-28827 To be added when MasterPasswordSalt is added to the user column
// MasterPasswordSalt = MasterPasswordUnlock?.Salt ?? Email.ToLower().Trim(),
Key = MasterPasswordUnlock?.MasterKeyWrappedUserKey ?? UserSymmetricKey
};
}

UserAsymmetricKeys.ToUser(user);

return user;
public RegisterFinishData ToData()
{
// TODO clean up flow once old fields are deprecated
// https://bitwarden.atlassian.net/browse/PM-27326
return new RegisterFinishData
{
MasterPasswordUnlockData = MasterPasswordUnlock?.ToData() ??
new MasterPasswordUnlockData
{
Kdf = new KdfSettings
{
KdfType = Kdf ?? throw new Exception("KdfType couldn't be found on either the MasterPasswordUnlockData or the Kdf property passed in."),
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)
Memory = KdfMemory,
Parallelism = KdfParallelism,
},
MasterKeyWrappedUserKey = UserSymmetricKey ?? throw new Exception("MasterKeyWrappedUserKey couldn't be found on either the MasterPasswordUnlockData or the UserSymmetricKey property passed in."),
// PM-28827 To be added when MasterPasswordSalt is added to the user column
Salt = Email.ToLowerInvariant().Trim(),
},
UserAccountKeysData = AccountKeys?.ToAccountKeysData() ??
new UserAccountKeysData
{
PublicKeyEncryptionKeyPairData = new PublicKeyEncryptionKeyPairData
(
UserAsymmetricKeys?.EncryptedPrivateKey ??
throw new Exception("WrappedPrivateKey couldn't be found in either AccountKeys or UserAsymmetricKeys."),
UserAsymmetricKeys?.PublicKey ??
throw new Exception("PublicKey couldn't be found in either AccountKeys or UserAsymmetricKeys")
),
},
MasterPasswordAuthenticationData = MasterPasswordAuthentication?.ToData() ??
new MasterPasswordAuthenticationData
{
Kdf = new KdfSettings
{
KdfType = Kdf ?? throw new Exception("KdfType couldn't be found on either the MasterPasswordUnlockData or the Kdf property passed in."),
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)
Memory = KdfMemory,
Parallelism = KdfParallelism,
},
MasterPasswordAuthenticationHash = MasterPasswordHash ?? throw new BadRequestException("MasterPasswordHash couldn't be found on either the MasterPasswordAuthenticationData or the MasterPasswordHash property passed in."),
Salt = Email.ToLowerInvariant().Trim(),
}
};
}

public RegisterFinishTokenType GetTokenType()
Expand Down Expand Up @@ -188,6 +254,13 @@ public IEnumerable<ValidationResult> Validate(ValidationContext validationContex
yield return new ValidationResult($"{nameof(MasterPasswordAuthentication)} not found on RequestModel", [nameof(MasterPasswordAuthentication)]);
}

if (AccountKeys == null && UserAsymmetricKeys == null)
{
yield return new ValidationResult(
$"{nameof(AccountKeys.PublicKeyEncryptionKeyPair.PublicKey)} and {nameof(AccountKeys.PublicKeyEncryptionKeyPair.WrappedPrivateKey)} not found in RequestModel",
[nameof(AccountKeys.PublicKeyEncryptionKeyPair.PublicKey), nameof(AccountKeys.PublicKeyEncryptionKeyPair.WrappedPrivateKey)]);
}

// 3. Lastly, validate access token type and presence. Must be done last because of yield break.
RegisterFinishTokenType tokenType;
var tokenTypeResolved = true;
Expand Down
21 changes: 11 additions & 10 deletions src/Core/Auth/UserFeatures/Registration/IRegisterUserCommand.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
๏ปฟusing Bit.Core.AdminConsole.Entities;
using Bit.Core.Entities;
using Bit.Core.KeyManagement.Models.Data;
using Microsoft.AspNetCore.Identity;

namespace Bit.Core.Auth.UserFeatures.Registration;
Expand Down Expand Up @@ -31,45 +32,45 @@ public interface IRegisterUserCommand
/// If the organization has a 2FA required policy enabled, email verification will be enabled for the user.
/// </summary>
/// <param name="user">The <see cref="User"/> to create</param>
/// <param name="masterPasswordHash">The hashed master password the user entered</param>
/// <param name="registerFinishData">Cryptographic data for finishing user registration</param>
/// <param name="orgInviteToken">The org invite token sent to the user via email</param>
/// <param name="orgUserId">The associated org user guid that was created at the time of invite</param>
/// <returns><see cref="IdentityResult"/></returns>
public Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User user, string masterPasswordHash, string orgInviteToken, Guid? orgUserId);
public Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User user, RegisterFinishData registerFinishData, string orgInviteToken, Guid? orgUserId);

/// <summary>
/// Creates a new user with a given master password hash, sends a welcome email, and raises the signup reference event.
/// If a valid email verification token is provided, the user will be created with their email verified.
/// An error will be thrown if the token is invalid or expired.
/// </summary>
/// <param name="user">The <see cref="User"/> to create</param>
/// <param name="masterPasswordHash">The hashed master password the user entered</param>
/// <param name="registerFinishData">Cryptographic data for finishing user registration</param>
/// <param name="emailVerificationToken">The email verification token sent to the user via email</param>
/// <returns><see cref="IdentityResult"/></returns>
public Task<IdentityResult> RegisterUserViaEmailVerificationToken(User user, string masterPasswordHash, string emailVerificationToken);
public Task<IdentityResult> RegisterUserViaEmailVerificationToken(User user, RegisterFinishData registerFinishData, string emailVerificationToken);

/// <summary>
/// Creates a new user with a given master password hash, sends a welcome email, and raises the signup reference event.
/// If a valid org sponsored free family plan invite token is provided, the user will be created with their email verified.
/// If the token is invalid or expired, an error will be thrown.
/// </summary>
/// <param name="user">The <see cref="User"/> to create</param>
/// <param name="masterPasswordHash">The hashed master password the user entered</param>
/// <param name="registerFinishData">Cryptographic data for finishing user registration</param>
/// <param name="orgSponsoredFreeFamilyPlanInviteToken">The org sponsored free family plan invite token sent to the user via email</param>
/// <returns><see cref="IdentityResult"/></returns>
public Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(User user, string masterPasswordHash, string orgSponsoredFreeFamilyPlanInviteToken);
public Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(User user, RegisterFinishData registerFinishData, string orgSponsoredFreeFamilyPlanInviteToken);

/// <summary>
/// Creates a new user with a given master password hash, sends a welcome email, and raises the signup reference event.
/// If a valid token is provided, the user will be created with their email verified.
/// If the token is invalid or expired, an error will be thrown.
/// </summary>
/// <param name="user">The <see cref="User"/> to create</param>
/// <param name="masterPasswordHash">The hashed master password the user entered</param>
/// <param name="registerFinishData">Cryptographic data for finishing user registration</param>
/// <param name="acceptEmergencyAccessInviteToken">The emergency access invite token sent to the user via email</param>
/// <param name="acceptEmergencyAccessId">The emergency access id (used to validate the token)</param>
/// <returns><see cref="IdentityResult"/></returns>
public Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToken(User user, string masterPasswordHash,
public Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToken(User user, RegisterFinishData registerFinishData,
string acceptEmergencyAccessInviteToken, Guid acceptEmergencyAccessId);

/// <summary>
Expand All @@ -78,10 +79,10 @@ public Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToken(User
/// If the token is invalid or expired, an error will be thrown.
/// </summary>
/// <param name="user">The <see cref="User"/> to create</param>
/// <param name="masterPasswordHash">The hashed master password the user entered</param>
/// <param name="registerFinishData">Cryptographic data for finishing user registration</param>
/// <param name="providerInviteToken">The provider invite token sent to the user via email</param>
/// <param name="providerUserId">The provider user id which is used to validate the invite token</param>
/// <returns><see cref="IdentityResult"/></returns>
public Task<IdentityResult> RegisterUserViaProviderInviteToken(User user, string masterPasswordHash, string providerInviteToken, Guid providerUserId);
public Task<IdentityResult> RegisterUserViaProviderInviteToken(User user, RegisterFinishData registerFinishData, string providerInviteToken, Guid providerUserId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Bit.Core.Billing.Extensions;
using Bit.Core.Entities;
using Bit.Core.Exceptions;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
using Bit.Core.Repositories;
using Bit.Core.Services;
Expand Down Expand Up @@ -107,7 +108,7 @@ public async Task<IdentityResult> RegisterSSOAutoProvisionedUserAsync(User user,
return result;
}

public async Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User user, string masterPasswordHash,
public async Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User user, RegisterFinishData registerFinishData,
string orgInviteToken, Guid? orgUserId)
{
TryValidateOrgInviteToken(orgInviteToken, orgUserId, user);
Expand All @@ -125,7 +126,7 @@ public async Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User us
user.EmailVerified = true;
}

var result = await _userService.CreateUserAsync(user, masterPasswordHash);
var result = await _userService.CreateUserAsync(user, registerFinishData);
var organization = await GetOrganizationUserOrganization(orgUserId ?? Guid.Empty, orgUser);
if (result == IdentityResult.Success)
{
Expand Down Expand Up @@ -257,7 +258,7 @@ private async Task SendAppropriateWelcomeEmailAsync(User user, string initiation
}
}

public async Task<IdentityResult> RegisterUserViaEmailVerificationToken(User user, string masterPasswordHash,
public async Task<IdentityResult> RegisterUserViaEmailVerificationToken(User user, RegisterFinishData registerFinishData,
string emailVerificationToken)
{
ValidateOpenRegistrationAllowed();
Expand All @@ -269,7 +270,7 @@ public async Task<IdentityResult> RegisterUserViaEmailVerificationToken(User use
user.Name = tokenable.Name;
user.ApiKey = CoreHelpers.SecureRandomString(30); // API key can't be null.

var result = await _userService.CreateUserAsync(user, masterPasswordHash);
var result = await _userService.CreateUserAsync(user, registerFinishData);
if (result == IdentityResult.Success)
{
await SendWelcomeEmailAsync(user);
Expand All @@ -278,7 +279,7 @@ public async Task<IdentityResult> RegisterUserViaEmailVerificationToken(User use
return result;
}

public async Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(User user, string masterPasswordHash,
public async Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken(User user, RegisterFinishData registerFinishData,
string orgSponsoredFreeFamilyPlanInviteToken)
{
ValidateOpenRegistrationAllowed();
Expand All @@ -288,7 +289,7 @@ public async Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamily
user.EmailVerified = true;
user.ApiKey = CoreHelpers.SecureRandomString(30); // API key can't be null.

var result = await _userService.CreateUserAsync(user, masterPasswordHash);
var result = await _userService.CreateUserAsync(user, registerFinishData);
if (result == IdentityResult.Success)
{
await SendWelcomeEmailAsync(user);
Expand All @@ -299,7 +300,7 @@ public async Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamily


// TODO: in future, consider how we can consolidate base registration logic to reduce code duplication
public async Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToken(User user, string masterPasswordHash,
public async Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToken(User user, RegisterFinishData registerFinishData,
string acceptEmergencyAccessInviteToken, Guid acceptEmergencyAccessId)
{
ValidateOpenRegistrationAllowed();
Expand All @@ -309,7 +310,7 @@ public async Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToke
user.EmailVerified = true;
user.ApiKey = CoreHelpers.SecureRandomString(30); // API key can't be null.

var result = await _userService.CreateUserAsync(user, masterPasswordHash);
var result = await _userService.CreateUserAsync(user, registerFinishData);
if (result == IdentityResult.Success)
{
await SendWelcomeEmailAsync(user);
Expand All @@ -318,7 +319,7 @@ public async Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToke
return result;
}

public async Task<IdentityResult> RegisterUserViaProviderInviteToken(User user, string masterPasswordHash,
public async Task<IdentityResult> RegisterUserViaProviderInviteToken(User user, RegisterFinishData registerFinishData,
string providerInviteToken, Guid providerUserId)
{
ValidateOpenRegistrationAllowed();
Expand All @@ -328,7 +329,7 @@ public async Task<IdentityResult> RegisterUserViaProviderInviteToken(User user,
user.EmailVerified = true;
user.ApiKey = CoreHelpers.SecureRandomString(30); // API key can't be null.

var result = await _userService.CreateUserAsync(user, masterPasswordHash);
var result = await _userService.CreateUserAsync(user, registerFinishData);
if (result == IdentityResult.Success)
{
await SendWelcomeEmailAsync(user);
Expand Down
1 change: 1 addition & 0 deletions src/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ public static class FeatureFlagKeys
public const string UnlockViaSdk = "unlock-via-sdk";
public const string NoLogoutOnKeyUpgradeRotation = "pm-31050-no-logout-key-upgrade-rotation";
public const string EnableAccountEncryptionV2JitPasswordRegistration = "enable-account-encryption-v2-jit-password-registration";
public const string EnableAccountEncryptionV2PasswordRegistration = "pm-27278-v2-password-registration";

/* Mobile Team */
public const string AndroidImportLoginsFlow = "import-logins-flow";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,21 @@ public void ValidateSaltUnchangedForUser(User user)
throw new BadRequestException("Invalid master password salt.");
}
}

public override bool Equals(object? obj)
{
if (obj is not MasterPasswordAuthenticationData other)
{
return false;
}

return Kdf.Equals(other.Kdf) &&
MasterPasswordAuthenticationHash == other.MasterPasswordAuthenticationHash &&
Salt == other.Salt;
}

public override int GetHashCode()
{
return HashCode.Combine(Kdf, MasterPasswordAuthenticationHash, Salt);
}
}
Loading
Loading