[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class PhabricatorAuthLoginController 4 extends PhabricatorAuthController { 5 6 private $providerKey; 7 private $extraURIData; 8 private $provider; 9 10 public function shouldRequireLogin() { 11 return false; 12 } 13 14 public function shouldAllowRestrictedParameter($parameter_name) { 15 // Whitelist the OAuth 'code' parameter. 16 17 if ($parameter_name == 'code') { 18 return true; 19 } 20 return parent::shouldAllowRestrictedParameter($parameter_name); 21 } 22 23 public function willProcessRequest(array $data) { 24 $this->providerKey = $data['pkey']; 25 $this->extraURIData = idx($data, 'extra'); 26 } 27 28 public function getExtraURIData() { 29 return $this->extraURIData; 30 } 31 32 public function processRequest() { 33 $request = $this->getRequest(); 34 $viewer = $request->getUser(); 35 36 $response = $this->loadProvider(); 37 if ($response) { 38 return $response; 39 } 40 41 $provider = $this->provider; 42 43 try { 44 list($account, $response) = $provider->processLoginRequest($this); 45 } catch (PhutilAuthUserAbortedException $ex) { 46 if ($viewer->isLoggedIn()) { 47 // If a logged-in user cancels, take them back to the external accounts 48 // panel. 49 $next_uri = '/settings/panel/external/'; 50 } else { 51 // If a logged-out user cancels, take them back to the auth start page. 52 $next_uri = '/'; 53 } 54 55 // User explicitly hit "Cancel". 56 $dialog = id(new AphrontDialogView()) 57 ->setUser($viewer) 58 ->setTitle(pht('Authentication Canceled')) 59 ->appendChild( 60 pht('You canceled authentication.')) 61 ->addCancelButton($next_uri, pht('Continue')); 62 return id(new AphrontDialogResponse())->setDialog($dialog); 63 } 64 65 if ($response) { 66 return $response; 67 } 68 69 if (!$account) { 70 throw new Exception( 71 'Auth provider failed to load an account from processLoginRequest()!'); 72 } 73 74 if ($account->getUserPHID()) { 75 // The account is already attached to a Phabricator user, so this is 76 // either a login or a bad account link request. 77 if (!$viewer->isLoggedIn()) { 78 if ($provider->shouldAllowLogin()) { 79 return $this->processLoginUser($account); 80 } else { 81 return $this->renderError( 82 pht( 83 'The external account ("%s") you just authenticated with is '. 84 'not configured to allow logins on this Phabricator install. '. 85 'An administrator may have recently disabled it.', 86 $provider->getProviderName())); 87 } 88 } else if ($viewer->getPHID() == $account->getUserPHID()) { 89 // This is either an attempt to re-link an existing and already 90 // linked account (which is silly) or a refresh of an external account 91 // (e.g., an OAuth account). 92 return id(new AphrontRedirectResponse()) 93 ->setURI('/settings/panel/external/'); 94 } else { 95 return $this->renderError( 96 pht( 97 'The external account ("%s") you just used to login is already '. 98 'associated with another Phabricator user account. Login to the '. 99 'other Phabricator account and unlink the external account before '. 100 'linking it to a new Phabricator account.', 101 $provider->getProviderName())); 102 } 103 } else { 104 // The account is not yet attached to a Phabricator user, so this is 105 // either a registration or an account link request. 106 if (!$viewer->isLoggedIn()) { 107 if ($provider->shouldAllowRegistration()) { 108 return $this->processRegisterUser($account); 109 } else { 110 return $this->renderError( 111 pht( 112 'The external account ("%s") you just authenticated with is '. 113 'not configured to allow registration on this Phabricator '. 114 'install. An administrator may have recently disabled it.', 115 $provider->getProviderName())); 116 } 117 } else { 118 if ($provider->shouldAllowAccountLink()) { 119 return $this->processLinkUser($account); 120 } else { 121 return $this->renderError( 122 pht( 123 'The external account ("%s") you just authenticated with is '. 124 'not configured to allow account linking on this Phabricator '. 125 'install. An administrator may have recently disabled it.', 126 $provider->getProviderName())); 127 } 128 } 129 } 130 131 // This should be unreachable, but fail explicitly if we get here somehow. 132 return new Aphront400Response(); 133 } 134 135 private function processLoginUser(PhabricatorExternalAccount $account) { 136 $user = id(new PhabricatorUser())->loadOneWhere( 137 'phid = %s', 138 $account->getUserPHID()); 139 140 if (!$user) { 141 return $this->renderError( 142 pht( 143 'The external account you just logged in with is not associated '. 144 'with a valid Phabricator user.')); 145 } 146 147 return $this->loginUser($user); 148 } 149 150 private function processRegisterUser(PhabricatorExternalAccount $account) { 151 $account_secret = $account->getAccountSecret(); 152 $register_uri = $this->getApplicationURI('register/'.$account_secret.'/'); 153 return $this->setAccountKeyAndContinue($account, $register_uri); 154 } 155 156 private function processLinkUser(PhabricatorExternalAccount $account) { 157 $account_secret = $account->getAccountSecret(); 158 $confirm_uri = $this->getApplicationURI('confirmlink/'.$account_secret.'/'); 159 return $this->setAccountKeyAndContinue($account, $confirm_uri); 160 } 161 162 private function setAccountKeyAndContinue( 163 PhabricatorExternalAccount $account, 164 $next_uri) { 165 166 if ($account->getUserPHID()) { 167 throw new Exception('Account is already registered or linked.'); 168 } 169 170 // Regenerate the registration secret key, set it on the external account, 171 // set a cookie on the user's machine, and redirect them to registration. 172 // See PhabricatorAuthRegisterController for discussion of the registration 173 // key. 174 175 $registration_key = Filesystem::readRandomCharacters(32); 176 $account->setProperty( 177 'registrationKey', 178 PhabricatorHash::digest($registration_key)); 179 180 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 181 $account->save(); 182 unset($unguarded); 183 184 $this->getRequest()->setTemporaryCookie( 185 PhabricatorCookies::COOKIE_REGISTRATION, 186 $registration_key); 187 188 return id(new AphrontRedirectResponse())->setURI($next_uri); 189 } 190 191 private function loadProvider() { 192 $provider = PhabricatorAuthProvider::getEnabledProviderByKey( 193 $this->providerKey); 194 195 if (!$provider) { 196 return $this->renderError( 197 pht( 198 'The account you are attempting to login with uses a nonexistent '. 199 'or disabled authentication provider (with key "%s"). An '. 200 'administrator may have recently disabled this provider.', 201 $this->providerKey)); 202 } 203 204 $this->provider = $provider; 205 206 return null; 207 } 208 209 protected function renderError($message) { 210 return $this->renderErrorPage( 211 pht('Login Failed'), 212 array($message)); 213 } 214 215 public function buildProviderPageResponse( 216 PhabricatorAuthProvider $provider, 217 $content) { 218 219 $crumbs = $this->buildApplicationCrumbs(); 220 221 if ($this->getRequest()->getUser()->isLoggedIn()) { 222 $crumbs->addTextCrumb(pht('Link Account'), $provider->getSettingsURI()); 223 } else { 224 $crumbs->addTextCrumb(pht('Login'), $this->getApplicationURI('start/')); 225 } 226 227 $crumbs->addTextCrumb($provider->getProviderName()); 228 229 return $this->buildApplicationPage( 230 array( 231 $crumbs, 232 $content, 233 ), 234 array( 235 'title' => pht('Login'), 236 )); 237 } 238 239 public function buildProviderErrorResponse( 240 PhabricatorAuthProvider $provider, 241 $message) { 242 243 $message = pht( 244 'Authentication provider ("%s") encountered an error during login. %s', 245 $provider->getProviderName(), 246 $message); 247 248 return $this->renderError($message); 249 } 250 251 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |