1- using Bit . Core . Entities ;
1+ #nullable enable
2+ using Bit . Core . Entities ;
23using Bit . Core . Enums ;
3- using Bit . Core . KeyManagement . Models . Api . Request ;
44using Bit . Core . Utilities ;
55
66namespace 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}
0 commit comments