@@ -212,8 +212,36 @@ export class UsersRouter extends ClassesRouter {
212212 }
213213 // Create the missing user but continue through the standard login path so
214214 // that all login-time policies, triggers, and session metadata remain unchanged.
215- signupSessionToken = await this . _autoSignupOnLogin ( req , autoSignupCredentials ) ;
216- user = await this . _authenticateUserFromRequest ( req ) ;
215+ try {
216+ signupSessionToken = await this . _autoSignupOnLogin ( req , autoSignupCredentials ) ;
217+ } catch ( signupError ) {
218+ // Another request created the user or user exists with wrong password
219+ // we try authenticating again in that case; if it works then it works.
220+ // and we continue with the "usual" login flow.
221+ if ( signupError . code === Parse . Error . DUPLICATE_VALUE ||
222+ signupError . code === Parse . Error . USERNAME_TAKEN ||
223+ signupError . code === Parse . Error . EMAIL_TAKEN ) {
224+ user = await this . _authenticateUserFromRequest ( req ) ;
225+ } else {
226+ throw signupError ;
227+ }
228+ }
229+ if ( signupSessionToken ) {
230+ // Discard the session issued by the signup shortcut; the login session we just
231+ // created is the single source of truth for the client.
232+ try {
233+ await req . config . database . destroy ( '_Session' , { sessionToken : signupSessionToken } ) ;
234+ } catch ( sessionError ) {
235+ if ( sessionError && sessionError . code !== Parse . Error . OBJECT_NOT_FOUND ) {
236+ logger . warn ( 'Failed to clean up auto sign-up session token' , sessionError ) ;
237+ }
238+ }
239+ }
240+ // If no user was set from the catch-clause (no race condition)
241+ // then we simply authenticate the user as usual.
242+ if ( ! user ) {
243+ user = await this . _authenticateUserFromRequest ( req ) ;
244+ }
217245 }
218246
219247 // Check if user has provided their required auth providers
@@ -269,10 +297,12 @@ export class UsersRouter extends ClassesRouter {
269297 ) ;
270298 if ( expiresAt < new Date ( ) )
271299 // fail of current time is past password expiry time
272- { throw new Parse . Error (
273- Parse . Error . OBJECT_NOT_FOUND ,
274- 'Your password has expired. Please reset your password.'
275- ) ; }
300+ {
301+ throw new Parse . Error (
302+ Parse . Error . OBJECT_NOT_FOUND ,
303+ 'Your password has expired. Please reset your password.'
304+ ) ;
305+ }
276306 }
277307 }
278308
@@ -300,7 +330,6 @@ export class UsersRouter extends ClassesRouter {
300330 { }
301331 ) ;
302332 }
303-
304333 const { sessionData, createSession } = RestWrite . createSession ( req . config , {
305334 userId : user . objectId ,
306335 createdWith : {
@@ -314,18 +343,6 @@ export class UsersRouter extends ClassesRouter {
314343
315344 await createSession ( ) ;
316345
317- if ( signupSessionToken ) {
318- // Discard the session issued by the signup shortcut; the login session we just
319- // created is the single source of truth for the client.
320- try {
321- await req . config . database . destroy ( '_Session' , { sessionToken : signupSessionToken } ) ;
322- } catch ( sessionError ) {
323- if ( sessionError && sessionError . code !== Parse . Error . OBJECT_NOT_FOUND ) {
324- logger . warn ( 'Failed to clean up auto sign-up session token' , sessionError ) ;
325- }
326- }
327- }
328-
329346 const afterLoginUser = Parse . User . fromJSON ( Object . assign ( { className : '_User' } , user ) ) ;
330347 await maybeRunTrigger (
331348 TriggerTypes . afterLogin ,
@@ -359,7 +376,7 @@ export class UsersRouter extends ClassesRouter {
359376 password : source . password ,
360377 } ;
361378 }
362-
379+
363380 // Returns data for auto-signup if autoSignupOnLogin is true and the error is that the user doesn't exist.
364381 // If the conditions don't match, we return `null`.
365382 // This gathers minimal credentials so that the signup path can rely on RestWrite's own validation.
@@ -724,7 +741,7 @@ export class UsersRouter extends ClassesRouter {
724741 const userString = req . auth && req . auth . user ? req . auth . user . id : undefined ;
725742 logger . error (
726743 `Failed running auth step challenge for ${ provider } for user ${ userString } with Error: ` +
727- JSON . stringify ( e ) ,
744+ JSON . stringify ( e ) ,
728745 {
729746 authenticationStep : 'challenge' ,
730747 error : e ,
0 commit comments