@@ -1664,6 +1664,20 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr
16641664 }
16651665 }
16661666
1667+ // If user is not found, check if there is an identity with the same email
1668+ // Only allow connecting to existing account if OAuth provider verified the email
1669+ if ($ user === false || $ user ->isEmpty ()) {
1670+ $ identityWithMatchingEmail = $ dbForProject ->findOne ('identities ' , [
1671+ Query::equal ('providerEmail ' , [$ email ]),
1672+ ]);
1673+ if (!$ identityWithMatchingEmail ->isEmpty ()) {
1674+ if (!$ isVerified ) {
1675+ $ failureRedirect (Exception::GENERAL_BAD_REQUEST );
1676+ }
1677+ $ user ->setAttributes ($ dbForProject ->getDocument ('users ' , $ identityWithMatchingEmail ->getAttribute ('userId ' ))->getArrayCopy ());
1678+ }
1679+ }
1680+
16671681 if ($ user === false || $ user ->isEmpty ()) { // Last option -> create the user
16681682 $ limit = $ project ->getAttribute ('auths ' , [])['limit ' ] ?? 0 ;
16691683
@@ -1675,14 +1689,6 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr
16751689 }
16761690 }
16771691
1678- // Makes sure this email is not already used in another identity
1679- $ identityWithMatchingEmail = $ dbForProject ->findOne ('identities ' , [
1680- Query::equal ('providerEmail ' , [$ email ]),
1681- ]);
1682- if (!$ identityWithMatchingEmail ->isEmpty ()) {
1683- $ failureRedirect (Exception::GENERAL_BAD_REQUEST ); /** Return a generic bad request to prevent exposing existing accounts */
1684- }
1685-
16861692 try {
16871693 $ emailCanonical = new Email ($ email );
16881694 } catch (Throwable ) {
@@ -1736,7 +1742,6 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, arr
17361742 'providerType ' => MESSAGE_TYPE_EMAIL ,
17371743 'identifier ' => $ email ,
17381744 ]));
1739-
17401745 } catch (Duplicate ) {
17411746 $ failureRedirect (Exception::USER_ALREADY_EXISTS );
17421747 }
0 commit comments