phorge/src/applications/auth/controller/PhabricatorAuthLoginController.php36e2d02d6ec5master
phorge/src/applications/auth/controller/PhabricatorAuthLoginController.php
36e2d02d6ec5master
PhabricatorAuthLoginController.php
PhabricatorAuthLoginController.php
c05ee9ed6844 | <?php | ||
---|---|---|---|
final class PhabricatorAuthLoginController | |||
extends PhabricatorAuthController { | |||
private $providerKey; | |||
a566ae373015 | private $extraURIData; | ||
c05ee9ed6844 | private $provider; | ||
public function shouldRequireLogin() { | |||
return false; | |||
} | |||
7176240717f2 | public function shouldAllowRestrictedParameter($parameter_name) { | ||
// Whitelist the OAuth 'code' parameter. | |||
if ($parameter_name == 'code') { | |||
return true; | |||
} | |||
return parent::shouldAllowRestrictedParameter($parameter_name); | |||
} | |||
c05ee9ed6844 | public function willProcessRequest(array $data) { | ||
$this->providerKey = $data['pkey']; | |||
a566ae373015 | $this->extraURIData = idx($data, 'extra'); | ||
} | |||
public function getExtraURIData() { | |||
return $this->extraURIData; | |||
c05ee9ed6844 | } | ||
public function processRequest() { | |||
$request = $this->getRequest(); | |||
$viewer = $request->getUser(); | |||
$response = $this->loadProvider(); | |||
if ($response) { | |||
return $response; | |||
} | |||
$provider = $this->provider; | |||
25eb401e18ae | try { | ||
list($account, $response) = $provider->processLoginRequest($this); | |||
} catch (PhutilAuthUserAbortedException $ex) { | |||
if ($viewer->isLoggedIn()) { | |||
// If a logged-in user cancels, take them back to the external accounts | |||
// panel. | |||
$next_uri = '/settings/panel/external/'; | |||
} else { | |||
// If a logged-out user cancels, take them back to the auth start page. | |||
$next_uri = '/'; | |||
} | |||
// User explicitly hit "Cancel". | |||
$dialog = id(new AphrontDialogView()) | |||
->setUser($viewer) | |||
->setTitle(pht('Authentication Canceled')) | |||
->appendChild( | |||
pht('You canceled authentication.')) | |||
->addCancelButton($next_uri, pht('Continue')); | |||
return id(new AphrontDialogResponse())->setDialog($dialog); | |||
} | |||
c05ee9ed6844 | if ($response) { | ||
return $response; | |||
} | |||
1329b7b51ef8 | if (!$account) { | ||
throw new Exception( | |||
36e2d02d6ec5 | pht( | ||
'Auth provider failed to load an account from %s!', | |||
'processLoginRequest()')); | |||
1329b7b51ef8 | } | ||
c05ee9ed6844 | if ($account->getUserPHID()) { | ||
// The account is already attached to a Phabricator user, so this is | |||
// either a login or a bad account link request. | |||
if (!$viewer->isLoggedIn()) { | |||
if ($provider->shouldAllowLogin()) { | |||
return $this->processLoginUser($account); | |||
} else { | |||
return $this->renderError( | |||
pht( | |||
'The external account ("%s") you just authenticated with is '. | |||
'not configured to allow logins on this Phabricator install. '. | |||
'An administrator may have recently disabled it.', | |||
$provider->getProviderName())); | |||
} | |||
} else if ($viewer->getPHID() == $account->getUserPHID()) { | |||
fe71b34c6883 | // This is either an attempt to re-link an existing and already | ||
// linked account (which is silly) or a refresh of an external account | |||
// (e.g., an OAuth account). | |||
return id(new AphrontRedirectResponse()) | |||
->setURI('/settings/panel/external/'); | |||
c05ee9ed6844 | } else { | ||
return $this->renderError( | |||
pht( | |||
49bd5721c5a7 | 'The external account ("%s") you just used to login is already '. | ||
c05ee9ed6844 | 'associated with another Phabricator user account. Login to the '. | ||
'other Phabricator account and unlink the external account before '. | |||
'linking it to a new Phabricator account.', | |||
$provider->getProviderName())); | |||
} | |||
} else { | |||
// The account is not yet attached to a Phabricator user, so this is | |||
// either a registration or an account link request. | |||
if (!$viewer->isLoggedIn()) { | |||
if ($provider->shouldAllowRegistration()) { | |||
return $this->processRegisterUser($account); | |||
} else { | |||
return $this->renderError( | |||
pht( | |||
'The external account ("%s") you just authenticated with is '. | |||
'not configured to allow registration on this Phabricator '. | |||
'install. An administrator may have recently disabled it.', | |||
$provider->getProviderName())); | |||
} | |||
} else { | |||
if ($provider->shouldAllowAccountLink()) { | |||
return $this->processLinkUser($account); | |||
} else { | |||
return $this->renderError( | |||
pht( | |||
'The external account ("%s") you just authenticated with is '. | |||
'not configured to allow account linking on this Phabricator '. | |||
104d3221d9b8 | 'install. An administrator may have recently disabled it.', | ||
$provider->getProviderName())); | |||
c05ee9ed6844 | } | ||
} | |||
} | |||
// This should be unreachable, but fail explicitly if we get here somehow. | |||
return new Aphront400Response(); | |||
} | |||
private function processLoginUser(PhabricatorExternalAccount $account) { | |||
104d3221d9b8 | $user = id(new PhabricatorUser())->loadOneWhere( | ||
'phid = %s', | |||
$account->getUserPHID()); | |||
if (!$user) { | |||
return $this->renderError( | |||
pht( | |||
'The external account you just logged in with is not associated '. | |||
'with a valid Phabricator user.')); | |||
} | |||
61a0c6d6e389 | return $this->loginUser($user); | ||
c05ee9ed6844 | } | ||
private function processRegisterUser(PhabricatorExternalAccount $account) { | |||
b040f889dee2 | $account_secret = $account->getAccountSecret(); | ||
$register_uri = $this->getApplicationURI('register/'.$account_secret.'/'); | |||
return $this->setAccountKeyAndContinue($account, $register_uri); | |||
} | |||
private function processLinkUser(PhabricatorExternalAccount $account) { | |||
$account_secret = $account->getAccountSecret(); | |||
$confirm_uri = $this->getApplicationURI('confirmlink/'.$account_secret.'/'); | |||
return $this->setAccountKeyAndContinue($account, $confirm_uri); | |||
} | |||
private function setAccountKeyAndContinue( | |||
PhabricatorExternalAccount $account, | |||
$next_uri) { | |||
c05ee9ed6844 | if ($account->getUserPHID()) { | ||
36e2d02d6ec5 | throw new Exception(pht('Account is already registered or linked.')); | ||
c05ee9ed6844 | } | ||
// Regenerate the registration secret key, set it on the external account, | |||
// set a cookie on the user's machine, and redirect them to registration. | |||
// See PhabricatorAuthRegisterController for discussion of the registration | |||
// key. | |||
$registration_key = Filesystem::readRandomCharacters(32); | |||
e71564fc75fd | $account->setProperty( | ||
'registrationKey', | |||
PhabricatorHash::digest($registration_key)); | |||
c05ee9ed6844 | |||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||
$account->save(); | |||
unset($unguarded); | |||
559c0fe88663 | $this->getRequest()->setTemporaryCookie( | ||
072741802350 | PhabricatorCookies::COOKIE_REGISTRATION, | ||
$registration_key); | |||
c05ee9ed6844 | |||
b040f889dee2 | return id(new AphrontRedirectResponse())->setURI($next_uri); | ||
c05ee9ed6844 | } | ||
private function loadProvider() { | |||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey( | |||
$this->providerKey); | |||
if (!$provider) { | |||
return $this->renderError( | |||
pht( | |||
'The account you are attempting to login with uses a nonexistent '. | |||
'or disabled authentication provider (with key "%s"). An '. | |||
'administrator may have recently disabled this provider.', | |||
$this->providerKey)); | |||
} | |||
$this->provider = $provider; | |||
return null; | |||
} | |||
61a0c6d6e389 | protected function renderError($message) { | ||
b040f889dee2 | return $this->renderErrorPage( | ||
pht('Login Failed'), | |||
array($message)); | |||
c05ee9ed6844 | } | ||
1329b7b51ef8 | public function buildProviderPageResponse( | ||
PhabricatorAuthProvider $provider, | |||
$content) { | |||
$crumbs = $this->buildApplicationCrumbs(); | |||
33c0b9423fa5 | $crumbs->setBorder(true); | ||
fded36cc2153 | |||
if ($this->getRequest()->getUser()->isLoggedIn()) { | |||
a5dc9067af0c | $crumbs->addTextCrumb(pht('Link Account'), $provider->getSettingsURI()); | ||
fded36cc2153 | } else { | ||
a5dc9067af0c | $crumbs->addTextCrumb(pht('Login'), $this->getApplicationURI('start/')); | ||
fded36cc2153 | } | ||
a5dc9067af0c | $crumbs->addTextCrumb($provider->getProviderName()); | ||
1329b7b51ef8 | |||
return $this->buildApplicationPage( | |||
array( | |||
$crumbs, | |||
$content, | |||
), | |||
array( | |||
'title' => pht('Login'), | |||
)); | |||
} | |||
7efee51c384d | public function buildProviderErrorResponse( | ||
PhabricatorAuthProvider $provider, | |||
$message) { | |||
$message = pht( | |||
'Authentication provider ("%s") encountered an error during login. %s', | |||
$provider->getProviderName(), | |||
$message); | |||
return $this->renderError($message); | |||
} | |||
c05ee9ed6844 | } |
Owner Packages
Owner Packages
- No Owners