From b038041dc600448c81c06c7b0f64c0d009245ca8 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 24 Oct 2015 04:50:36 -0700 Subject: [PATCH] Prevent duplicate account links from being created by swapping logins and then refreshing the link Summary: Fixes T6707. Users can currently do this: - Log in to a service (like Facebook or Google) with account "A". - Link their Phabricator account to that account. - Log out of Facebook, log back in with account "B". - Refresh the account link from {nav Settings > External Accounts}. When they do this, we write a second account link (between their Phabricator account and account "B"). However, the rest of the codebase assumes accounts are singly-linked, so this breaks down elsewhere. For now, decline to link the second account. We'll permit this some day, but need to do more work to allow it, and the need is very rare. Test Plan: - Followed the steps above, hit the new error. - Logged back in to the proper account and did a link refresh (which worked). {F905562} Reviewers: chad Reviewed By: chad Maniphest Tasks: T6707 Differential Revision: https://secure.phabricator.com/D14319 --- .../PhabricatorAuthLoginController.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/applications/auth/controller/PhabricatorAuthLoginController.php b/src/applications/auth/controller/PhabricatorAuthLoginController.php index 65d462cb8e..be610e223a 100644 --- a/src/applications/auth/controller/PhabricatorAuthLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthLoginController.php @@ -113,6 +113,27 @@ final class PhabricatorAuthLoginController $provider->getProviderName())); } } else { + + // If the user already has a linked account of this type, prevent them + // from linking a second account. This can happen if they swap logins + // and then refresh the account link. See T6707. We will eventually + // allow this after T2549. + $existing_accounts = id(new PhabricatorExternalAccountQuery()) + ->setViewer($viewer) + ->withUserPHIDs(array($viewer->getPHID())) + ->withAccountTypes(array($account->getAccountType())) + ->execute(); + if ($existing_accounts) { + return $this->renderError( + pht( + 'Your Phabricator account is already connected to an external '. + 'account on this provider ("%s"), but you are currently logged '. + 'in to the provider with a different account. Log out of the '. + 'external service, then log back in with the correct account '. + 'before refreshing the account link.', + $provider->getProviderName())); + } + if ($provider->shouldAllowAccountLink()) { return $this->processLinkUser($account); } else {