@@ -51,6 +51,10 @@ public async Task<OneOf<User, IdentityError[]>> PrepareSetInitialMasterPasswordA
5151 EnsureUserIsHydrated ( user ) ;
5252 setInitialData . ValidateDataForUser ( user ) ;
5353
54+ // Note: Keep "unlock then authenticate" pattern in mind.
55+ // This is a purposeful inversion of that principle:
56+ // Authentication is derivative of unlock, and is the mechanism for validation;
57+ // eager validation keeps the logic easier to reason about, so it is performed first.
5458 var result = await UpdateExistingPasswordHashAsync (
5559 user ,
5660 setInitialData . MasterPasswordAuthentication . MasterPasswordAuthenticationHash ,
@@ -67,7 +71,7 @@ public async Task<OneOf<User, IdentityError[]>> PrepareSetInitialMasterPasswordA
6771 // Set salt on the user
6872 user . MasterPasswordSalt = setInitialData . MasterPasswordUnlock . Salt ;
6973
70- // Always override the master password hint, even if it's null.
74+ // Always override the master password hint, even if it's null
7175 user . MasterPasswordHint = setInitialData . MasterPasswordHint ;
7276
7377 // Update time markers on the user
@@ -103,6 +107,10 @@ public UpdateUserData BuildUpdateUserDelegateSetInitialMasterPassword(
103107
104108 return async ( connection , transaction ) =>
105109 {
110+ // Note: Keep "unlock then authenticate" pattern in mind.
111+ // This is a purposeful inversion of that principle:
112+ // Authentication is derivative of unlock, and is the mechanism for validation;
113+ // eager validation keeps the logic easier to reason about, so it is performed first.
106114 if ( setInitialData . ValidatePassword )
107115 {
108116 var validate = await ValidatePasswordInternalAsync ( user ,
@@ -139,6 +147,10 @@ public async Task<OneOf<User, IdentityError[]>> PrepareUpdateExistingMasterPassw
139147 EnsureUserIsHydrated ( user ) ;
140148 updateExistingData . ValidateDataForUser ( user ) ;
141149
150+ // Note: Keep "unlock then authenticate" pattern in mind.
151+ // This is a purposeful inversion of that principle:
152+ // Authentication is derivative of unlock, and is the mechanism for validation;
153+ // eager validation keeps the logic easier to reason about, so it is performed first.
142154 var result = await UpdateExistingPasswordHashAsync (
143155 user ,
144156 updateExistingData . MasterPasswordAuthentication . MasterPasswordAuthenticationHash ,
@@ -150,13 +162,13 @@ public async Task<OneOf<User, IdentityError[]>> PrepareUpdateExistingMasterPassw
150162 return result . Errors . ToArray ( ) ;
151163 }
152164
153- var now = _timeProvider . GetUtcNow ( ) . UtcDateTime ;
154-
155165 user . Key = updateExistingData . MasterPasswordUnlock . MasterKeyWrappedUserKey ;
156166
157- // Always override the master password hint, even if it's null.
167+ // Always override the master password hint, even if it's null
158168 user . MasterPasswordHint = updateExistingData . MasterPasswordHint ;
159169
170+ // Update time markers on the user
171+ var now = _timeProvider . GetUtcNow ( ) . UtcDateTime ;
160172 user . LastPasswordChangeDate = now ;
161173 user . RevisionDate = user . AccountRevisionDate = now ;
162174
@@ -170,6 +182,10 @@ public async Task<OneOf<User, IdentityError[]>> SaveUpdateExistingMasterPassword
170182 EnsureUserIsHydrated ( user ) ;
171183 updateExistingExistingData . ValidateDataForUser ( user ) ;
172184
185+ // Note: Keep "unlock then authenticate" pattern in mind.
186+ // This is a purposeful inversion of that principle:
187+ // Authentication is derivative of unlock, and is the mechanism for validation;
188+ // eager validation keeps the logic easier to reason about, so it is performed first.
173189 var result = await UpdateExistingPasswordHashAsync (
174190 user ,
175191 updateExistingExistingData . MasterPasswordAuthentication . MasterPasswordAuthenticationHash ,
@@ -181,14 +197,14 @@ public async Task<OneOf<User, IdentityError[]>> SaveUpdateExistingMasterPassword
181197 return result . Errors . ToArray ( ) ;
182198 }
183199
184- var now = _timeProvider . GetUtcNow ( ) . UtcDateTime ;
185-
186200 user . Key = updateExistingExistingData . MasterPasswordUnlock . MasterKeyWrappedUserKey ;
187201 SetKdfStateOnUser ( user , updateExistingExistingData . MasterPasswordUnlock . Kdf ) ;
188202
189- // Always override the master password hint, even if it's null.
203+ // Always override the master password hint, even if it's null
190204 user . MasterPasswordHint = updateExistingExistingData . MasterPasswordHint ;
191205
206+ // Update time markers on the user
207+ var now = _timeProvider . GetUtcNow ( ) . UtcDateTime ;
192208 user . LastPasswordChangeDate = now ;
193209 user . LastKdfChangeDate = now ;
194210 user . RevisionDate = user . AccountRevisionDate = now ;
0 commit comments