From bae194e866f37db4bd3a0a178311bb39e6d250ac Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 18 Dec 2025 15:59:33 +0400 Subject: [PATCH] Link account by email during OAuth --- app/controllers/api/account.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 65af15d1fe..0b279b5534 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1664,6 +1664,20 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } + // If user is not found, check if there is an identity with the same email + // Only allow connecting to existing account if OAuth provider verified the email + if ($user === false || $user->isEmpty()) { + $identityWithMatchingEmail = $dbForProject->findOne('identities', [ + Query::equal('providerEmail', [$email]), + ]); + if (!$identityWithMatchingEmail->isEmpty()) { + if (!$isVerified) { + $failureRedirect(Exception::GENERAL_BAD_REQUEST); + } + $user->setAttributes($dbForProject->getDocument('users', $identityWithMatchingEmail->getAttribute('userId'))->getArrayCopy()); + } + } + if ($user === false || $user->isEmpty()) { // Last option -> create the user $limit = $project->getAttribute('auths', [])['limit'] ?? 0; @@ -1675,14 +1689,6 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } } - // Makes sure this email is not already used in another identity - $identityWithMatchingEmail = $dbForProject->findOne('identities', [ - Query::equal('providerEmail', [$email]), - ]); - if (!$identityWithMatchingEmail->isEmpty()) { - $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ - } - try { $emailCanonical = new Email($email); } catch (Throwable) { @@ -1736,7 +1742,6 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ])); - } catch (Duplicate) { $failureRedirect(Exception::USER_ALREADY_EXISTS); }