Skip to content

Commit 029a5f6

Browse files
Revert "feat(register): [PM-27084] Account Register Uses New Data Types (#6715)" (#6854)
This reverts commit 8cb8030.
1 parent 8cb8030 commit 029a5f6

19 files changed

Lines changed: 63 additions & 1045 deletions

File tree

src/Api/Auth/Models/Request/Accounts/PasswordRequestModel.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.ComponentModel.DataAnnotations;
2-
using Bit.Core.KeyManagement.Models.Api.Request;
1+
#nullable enable
2+
3+
using System.ComponentModel.DataAnnotations;
4+
using Bit.Api.KeyManagement.Models.Requests;
35

46
namespace Bit.Api.Auth.Models.Request.Accounts;
57

src/Api/Auth/Models/Request/Accounts/SetInitialPasswordRequestModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel.DataAnnotations;
2+
using Bit.Api.KeyManagement.Models.Requests;
23
using Bit.Core.Auth.Models.Api.Request.Accounts;
34
using Bit.Core.Auth.Models.Data;
45
using Bit.Core.Entities;

src/Core/KeyManagement/Models/Api/Request/KdfRequestModel.cs renamed to src/Api/KeyManagement/Models/Requests/KdfRequestModel.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
using System.ComponentModel.DataAnnotations;
22
using Bit.Core.Enums;
33
using Bit.Core.KeyManagement.Models.Data;
4-
using Bit.Core.Utilities;
54

6-
namespace Bit.Core.KeyManagement.Models.Api.Request;
5+
namespace Bit.Api.KeyManagement.Models.Requests;
76

8-
public class KdfRequestModel : IValidatableObject
7+
public class KdfRequestModel
98
{
109
[Required]
1110
public required KdfType KdfType { get; init; }
@@ -24,10 +23,4 @@ public KdfSettings ToData()
2423
Parallelism = Parallelism
2524
};
2625
}
27-
28-
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
29-
{
30-
// Generic per-request KDF validation for any request model embedding KdfRequestModel
31-
return KdfSettingsValidator.Validate(ToData());
32-
}
3326
}

src/Core/KeyManagement/Models/Api/Request/MasterPasswordAuthenticationDataRequestModel.cs renamed to src/Api/KeyManagement/Models/Requests/MasterPasswordAuthenticationDataRequestModel.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
using System.ComponentModel.DataAnnotations;
22
using Bit.Core.KeyManagement.Models.Data;
33

4-
namespace Bit.Core.KeyManagement.Models.Api.Request;
4+
namespace Bit.Api.KeyManagement.Models.Requests;
55

6-
/// <summary>
7-
/// Use this datatype when interfacing with requests to create a separation of concern.
8-
/// See <see cref="MasterPasswordAuthenticationData"/> to use for commands, queries, services.
9-
/// </summary>
106
public class MasterPasswordAuthenticationDataRequestModel
117
{
128
public required KdfRequestModel Kdf { get; init; }

src/Core/KeyManagement/Models/Api/Request/MasterPasswordUnlockDataRequestModel.cs renamed to src/Api/KeyManagement/Models/Requests/MasterPasswordUnlockDataRequestModel.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22
using Bit.Core.KeyManagement.Models.Data;
33
using Bit.Core.Utilities;
44

5-
namespace Bit.Core.KeyManagement.Models.Api.Request;
5+
namespace Bit.Api.KeyManagement.Models.Requests;
66

7-
/// <summary>
8-
/// Use this datatype when interfacing with requests to create a separation of concern.
9-
/// See <see cref="MasterPasswordUnlockData"/> to use for commands, queries, services.
10-
/// </summary>
117
public class MasterPasswordUnlockDataRequestModel
128
{
139
public required KdfRequestModel Kdf { get; init; }
Lines changed: 16 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
using Bit.Core.Entities;
1+
#nullable enable
2+
using Bit.Core.Entities;
23
using Bit.Core.Enums;
3-
using Bit.Core.KeyManagement.Models.Api.Request;
44
using Bit.Core.Utilities;
55

66
namespace Bit.Core.Auth.Models.Api.Request.Accounts;
@@ -21,32 +21,19 @@ public class RegisterFinishRequestModel : IValidatableObject
2121
public required string Email { get; set; }
2222
public string? EmailVerificationToken { get; set; }
2323

24-
public MasterPasswordAuthenticationDataRequestModel? MasterPasswordAuthentication { get; set; }
25-
public MasterPasswordUnlockDataRequestModel? MasterPasswordUnlock { get; set; }
26-
27-
// PM-28143 - Remove property below (made optional during migration to MasterPasswordUnlockData)
2824
[StringLength(1000)]
29-
// Made optional but there will still be a thrown error if it does not exist either here or
30-
// in the MasterPasswordAuthenticationData.
31-
public string? MasterPasswordHash { get; set; }
25+
public required string MasterPasswordHash { get; set; }
3226

3327
[StringLength(50)]
3428
public string? MasterPasswordHint { get; set; }
3529

36-
// PM-28143 - Remove property below (made optional during migration to MasterPasswordUnlockData)
37-
// Made optional but there will still be a thrown error if it does not exist either here or
38-
// in the MasterPasswordAuthenticationData.
39-
public string? UserSymmetricKey { get; set; }
30+
public required string UserSymmetricKey { get; set; }
4031

4132
public required KeysRequestModel UserAsymmetricKeys { get; set; }
4233

43-
// PM-28143 - Remove line below (made optional during migration to MasterPasswordUnlockData)
44-
public KdfType? Kdf { get; set; }
45-
// PM-28143 - Remove line below (made optional during migration to MasterPasswordUnlockData)
46-
public int? KdfIterations { get; set; }
47-
// PM-28143 - Remove line below
34+
public required KdfType Kdf { get; set; }
35+
public required int KdfIterations { get; set; }
4836
public int? KdfMemory { get; set; }
49-
// PM-28143 - Remove line below
5037
public int? KdfParallelism { get; set; }
5138

5239
public Guid? OrganizationUserId { get; set; }
@@ -67,14 +54,11 @@ public User ToUser()
6754
{
6855
Email = Email,
6956
MasterPasswordHint = MasterPasswordHint,
70-
Kdf = (KdfType)(MasterPasswordUnlock?.Kdf.KdfType ?? Kdf)!,
71-
KdfIterations = (int)(MasterPasswordUnlock?.Kdf.Iterations ?? KdfIterations)!,
72-
// KdfMemory and KdfParallelism are optional (only used for Argon2id)
73-
KdfMemory = MasterPasswordUnlock?.Kdf.Memory ?? KdfMemory,
74-
KdfParallelism = MasterPasswordUnlock?.Kdf.Parallelism ?? KdfParallelism,
75-
// PM-28827 To be added when MasterPasswordSalt is added to the user column
76-
// MasterPasswordSalt = MasterPasswordUnlock?.Salt ?? Email.ToLower().Trim(),
77-
Key = MasterPasswordUnlock?.MasterKeyWrappedUserKey ?? UserSymmetricKey
57+
Kdf = Kdf,
58+
KdfIterations = KdfIterations,
59+
KdfMemory = KdfMemory,
60+
KdfParallelism = KdfParallelism,
61+
Key = UserSymmetricKey,
7862
};
7963

8064
UserAsymmetricKeys.ToUser(user);
@@ -88,182 +72,29 @@ public RegisterFinishTokenType GetTokenType()
8872
{
8973
return RegisterFinishTokenType.EmailVerification;
9074
}
91-
if (!string.IsNullOrEmpty(OrgInviteToken)
92-
&& OrganizationUserId.HasValue
93-
&& OrganizationUserId.Value != Guid.Empty)
75+
if (!string.IsNullOrEmpty(OrgInviteToken) && OrganizationUserId.HasValue)
9476
{
9577
return RegisterFinishTokenType.OrganizationInvite;
9678
}
9779
if (!string.IsNullOrWhiteSpace(OrgSponsoredFreeFamilyPlanToken))
9880
{
9981
return RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan;
10082
}
101-
if (!string.IsNullOrWhiteSpace(AcceptEmergencyAccessInviteToken)
102-
&& AcceptEmergencyAccessId.HasValue
103-
&& AcceptEmergencyAccessId.Value != Guid.Empty)
83+
if (!string.IsNullOrWhiteSpace(AcceptEmergencyAccessInviteToken) && AcceptEmergencyAccessId.HasValue)
10484
{
10585
return RegisterFinishTokenType.EmergencyAccessInvite;
10686
}
107-
if (!string.IsNullOrWhiteSpace(ProviderInviteToken)
108-
&& ProviderUserId.HasValue
109-
&& ProviderUserId.Value != Guid.Empty)
87+
if (!string.IsNullOrWhiteSpace(ProviderInviteToken) && ProviderUserId.HasValue)
11088
{
11189
return RegisterFinishTokenType.ProviderInvite;
11290
}
11391

11492
throw new InvalidOperationException("Invalid token type.");
11593
}
11694

95+
11796
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
11897
{
119-
// 1. Authentication data containing hash and hash at root level check
120-
if (MasterPasswordAuthentication != null && MasterPasswordHash != null)
121-
{
122-
if (MasterPasswordAuthentication.MasterPasswordAuthenticationHash != MasterPasswordHash)
123-
{
124-
yield return new ValidationResult(
125-
$"{nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash)} and root level {nameof(MasterPasswordHash)} provided and are not equal. Only provide one.",
126-
[nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash), nameof(MasterPasswordHash)]);
127-
}
128-
} // 1.5 if there is no master password hash that is unacceptable even though they are both optional in the model
129-
else if (MasterPasswordAuthentication == null && MasterPasswordHash == null)
130-
{
131-
yield return new ValidationResult(
132-
$"{nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash)} and {nameof(MasterPasswordHash)} not found on request, one needs to be defined.",
133-
[nameof(MasterPasswordAuthentication.MasterPasswordAuthenticationHash), nameof(MasterPasswordHash)]);
134-
}
135-
136-
// 2. Validate kdf settings.
137-
if (MasterPasswordUnlock != null)
138-
{
139-
foreach (var validationResult in KdfSettingsValidator.Validate(MasterPasswordUnlock.ToData().Kdf))
140-
{
141-
yield return validationResult;
142-
}
143-
}
144-
145-
if (MasterPasswordAuthentication != null)
146-
{
147-
foreach (var validationResult in KdfSettingsValidator.Validate(MasterPasswordAuthentication.ToData().Kdf))
148-
{
149-
yield return validationResult;
150-
}
151-
}
152-
153-
// 3. Validate root kdf values if kdf values are not in the unlock and authentication.
154-
if (MasterPasswordUnlock == null && MasterPasswordAuthentication == null)
155-
{
156-
var hasMissingRequiredKdfInputs = false;
157-
if (Kdf == null)
158-
{
159-
yield return new ValidationResult($"{nameof(Kdf)} not found on RequestModel", [nameof(Kdf)]);
160-
hasMissingRequiredKdfInputs = true;
161-
}
162-
if (KdfIterations == null)
163-
{
164-
yield return new ValidationResult($"{nameof(KdfIterations)} not found on RequestModel", [nameof(KdfIterations)]);
165-
hasMissingRequiredKdfInputs = true;
166-
}
167-
168-
if (!hasMissingRequiredKdfInputs)
169-
{
170-
foreach (var validationResult in KdfSettingsValidator.Validate(
171-
Kdf!.Value,
172-
KdfIterations!.Value,
173-
KdfMemory,
174-
KdfParallelism))
175-
{
176-
yield return validationResult;
177-
}
178-
}
179-
}
180-
else if (MasterPasswordUnlock == null && MasterPasswordAuthentication != null)
181-
{
182-
// Authentication provided but Unlock missing
183-
yield return new ValidationResult($"{nameof(MasterPasswordUnlock)} not found on RequestModel", [nameof(MasterPasswordUnlock)]);
184-
}
185-
else if (MasterPasswordUnlock != null && MasterPasswordAuthentication == null)
186-
{
187-
// Unlock provided but Authentication missing
188-
yield return new ValidationResult($"{nameof(MasterPasswordAuthentication)} not found on RequestModel", [nameof(MasterPasswordAuthentication)]);
189-
}
190-
191-
// 3. Lastly, validate access token type and presence. Must be done last because of yield break.
192-
RegisterFinishTokenType tokenType;
193-
var tokenTypeResolved = true;
194-
try
195-
{
196-
tokenType = GetTokenType();
197-
}
198-
catch (InvalidOperationException)
199-
{
200-
tokenTypeResolved = false;
201-
tokenType = default;
202-
}
203-
204-
if (!tokenTypeResolved)
205-
{
206-
yield return new ValidationResult("No valid registration token provided");
207-
yield break;
208-
}
209-
210-
switch (tokenType)
211-
{
212-
case RegisterFinishTokenType.EmailVerification:
213-
if (string.IsNullOrEmpty(EmailVerificationToken))
214-
{
215-
yield return new ValidationResult(
216-
$"{nameof(EmailVerificationToken)} absent when processing register/finish.",
217-
[nameof(EmailVerificationToken)]);
218-
}
219-
break;
220-
case RegisterFinishTokenType.OrganizationInvite:
221-
if (string.IsNullOrEmpty(OrgInviteToken))
222-
{
223-
yield return new ValidationResult(
224-
$"{nameof(OrgInviteToken)} absent when processing register/finish.",
225-
[nameof(OrgInviteToken)]);
226-
}
227-
break;
228-
case RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan:
229-
if (string.IsNullOrEmpty(OrgSponsoredFreeFamilyPlanToken))
230-
{
231-
yield return new ValidationResult(
232-
$"{nameof(OrgSponsoredFreeFamilyPlanToken)} absent when processing register/finish.",
233-
[nameof(OrgSponsoredFreeFamilyPlanToken)]);
234-
}
235-
break;
236-
case RegisterFinishTokenType.EmergencyAccessInvite:
237-
if (string.IsNullOrEmpty(AcceptEmergencyAccessInviteToken))
238-
{
239-
yield return new ValidationResult(
240-
$"{nameof(AcceptEmergencyAccessInviteToken)} absent when processing register/finish.",
241-
[nameof(AcceptEmergencyAccessInviteToken)]);
242-
}
243-
if (!AcceptEmergencyAccessId.HasValue || AcceptEmergencyAccessId.Value == Guid.Empty)
244-
{
245-
yield return new ValidationResult(
246-
$"{nameof(AcceptEmergencyAccessId)} absent when processing register/finish.",
247-
[nameof(AcceptEmergencyAccessId)]);
248-
}
249-
break;
250-
case RegisterFinishTokenType.ProviderInvite:
251-
if (string.IsNullOrEmpty(ProviderInviteToken))
252-
{
253-
yield return new ValidationResult(
254-
$"{nameof(ProviderInviteToken)} absent when processing register/finish.",
255-
[nameof(ProviderInviteToken)]);
256-
}
257-
if (!ProviderUserId.HasValue || ProviderUserId.Value == Guid.Empty)
258-
{
259-
yield return new ValidationResult(
260-
$"{nameof(ProviderUserId)} absent when processing register/finish.",
261-
[nameof(ProviderUserId)]);
262-
}
263-
break;
264-
default:
265-
yield return new ValidationResult("Invalid registration finish request");
266-
break;
267-
}
98+
return KdfSettingsValidator.Validate(Kdf, KdfIterations, KdfMemory, KdfParallelism);
26899
}
269100
}

src/Core/Entities/User.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using Bit.Core.Utilities;
88
using Microsoft.AspNetCore.Identity;
99

10+
#nullable enable
11+
1012
namespace Bit.Core.Entities;
1113

1214
public class User : ITableObject<Guid>, IStorableSubscriber, IRevisable, ITwoFactorProvidersUser
@@ -49,7 +51,7 @@ public class User : ITableObject<Guid>, IStorableSubscriber, IRevisable, ITwoFac
4951
public string? Key { get; set; }
5052
/// <summary>
5153
/// The raw public key, without a signature from the user's signature key.
52-
/// </summary>
54+
/// </summary>
5355
public string? PublicKey { get; set; }
5456
/// <summary>
5557
/// User key wrapped private key.
@@ -105,8 +107,6 @@ public class User : ITableObject<Guid>, IStorableSubscriber, IRevisable, ITwoFac
105107
public DateTime? LastKeyRotationDate { get; set; }
106108
public DateTime? LastEmailChangeDate { get; set; }
107109
public bool VerifyDevices { get; set; } = true;
108-
// PM-28827 Uncomment below line.
109-
// public string? MasterPasswordSalt { get; set; }
110110

111111
public string GetMasterPasswordSalt()
112112
{

src/Core/KeyManagement/Models/Data/MasterPasswordAuthenticationData.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
using Bit.Core.Entities;
22
using Bit.Core.Exceptions;
3-
using Bit.Core.KeyManagement.Models.Api.Request;
43

54
namespace Bit.Core.KeyManagement.Models.Data;
65

7-
/// <summary>
8-
/// Use this datatype when interfacing with commands, queries, services to create a separation of concern.
9-
/// See <see cref="MasterPasswordAuthenticationDataRequestModel"/> to use for requests.
10-
/// </summary>
116
public class MasterPasswordAuthenticationData
127
{
138
public required KdfSettings Kdf { get; init; }

src/Core/KeyManagement/Models/Data/MasterPasswordUnlockAndAuthenticationData.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Bit.Core.Entities;
1+
#nullable enable
2+
using Bit.Core.Entities;
23
using Bit.Core.Enums;
34

45
namespace Bit.Core.KeyManagement.Models.Data;

src/Core/KeyManagement/Models/Data/MasterPasswordUnlockData.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
using Bit.Core.Entities;
22
using Bit.Core.Exceptions;
3-
using Bit.Core.KeyManagement.Models.Api.Request;
43

54
namespace Bit.Core.KeyManagement.Models.Data;
65

7-
/// <summary>
8-
/// Use this datatype when interfacing with commands, queries, services to create a separation of concern.
9-
/// See <see cref="MasterPasswordUnlockDataRequestModel"/> to use for requests.
10-
/// </summary>
116
public class MasterPasswordUnlockData
127
{
138
public required KdfSettings Kdf { get; init; }

0 commit comments

Comments
 (0)