Differential D14050 Diff 33959 src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php
<?php | <?php | ||||
final class PhabricatorOAuthServerAuthController | final class PhabricatorOAuthServerAuthController | ||||
extends PhabricatorAuthController { | extends PhabricatorOAuthServerController { | ||||
public function shouldRequireLogin() { | public function handleRequest(AphrontRequest $request) { | ||||
return true; | $viewer = $this->getViewer(); | ||||
} | |||||
public function processRequest() { | |||||
$request = $this->getRequest(); | |||||
$viewer = $request->getUser(); | |||||
$server = new PhabricatorOAuthServer(); | $server = new PhabricatorOAuthServer(); | ||||
$client_phid = $request->getStr('client_id'); | $client_phid = $request->getStr('client_id'); | ||||
$scope = $request->getStr('scope'); | $scope = $request->getStr('scope'); | ||||
$redirect_uri = $request->getStr('redirect_uri'); | $redirect_uri = $request->getStr('redirect_uri'); | ||||
$response_type = $request->getStr('response_type'); | $response_type = $request->getStr('response_type'); | ||||
// state is an opaque value the client sent us for their own purposes | // state is an opaque value the client sent us for their own purposes | ||||
// we just need to send it right back to them in the response! | // we just need to send it right back to them in the response! | ||||
$state = $request->getStr('state'); | $state = $request->getStr('state'); | ||||
if (!$client_phid) { | if (!$client_phid) { | ||||
return $this->buildErrorResponse( | return $this->buildErrorResponse( | ||||
'invalid_request', | 'invalid_request', | ||||
pht('Malformed Request'), | pht('Malformed Request'), | ||||
pht( | pht( | ||||
'Required parameter %s was not present in the request.', | 'Required parameter %s was not present in the request.', | ||||
phutil_tag('strong', array(), 'client_id'))); | phutil_tag('strong', array(), 'client_id'))); | ||||
} | } | ||||
// We require that users must be able to see an OAuth application | |||||
// in order to authorize it. This allows an application's visibility | |||||
// policy to be used to restrict authorized users. | |||||
try { | |||||
$client = id(new PhabricatorOAuthServerClientQuery()) | |||||
->setViewer($viewer) | |||||
->withPHIDs(array($client_phid)) | |||||
->executeOne(); | |||||
} catch (PhabricatorPolicyException $ex) { | |||||
$ex->setContext(self::CONTEXT_AUTHORIZE); | |||||
throw $ex; | |||||
} | |||||
$server->setUser($viewer); | $server->setUser($viewer); | ||||
$is_authorized = false; | $is_authorized = false; | ||||
$authorization = null; | $authorization = null; | ||||
$uri = null; | $uri = null; | ||||
$name = null; | $name = null; | ||||
// one giant try / catch around all the exciting database stuff so we | // one giant try / catch around all the exciting database stuff so we | ||||
// can return a 'server_error' response if something goes wrong! | // can return a 'server_error' response if something goes wrong! | ||||
try { | try { | ||||
try { | |||||
$client = id(new PhabricatorOAuthServerClientQuery()) | |||||
->setViewer($viewer) | |||||
->withPHIDs(array($client_phid)) | |||||
->executeOne(); | |||||
} catch (PhabricatorPolicyException $ex) { | |||||
// We require that users must be able to see an OAuth application | |||||
// in order to authorize it. This allows an application's visibility | |||||
// policy to be used to restrict authorized users. | |||||
// None of the OAuth error responses are a perfect fit for this, but | |||||
// 'invalid_client' seems closest. | |||||
return $this->buildErrorResponse( | |||||
'invalid_client', | |||||
pht('Not Authorized'), | |||||
pht('You are not authorized to authenticate.')); | |||||
} | |||||
if (!$client) { | if (!$client) { | ||||
return $this->buildErrorResponse( | return $this->buildErrorResponse( | ||||
'invalid_request', | 'invalid_request', | ||||
pht('Invalid Client Application'), | pht('Invalid Client Application'), | ||||
pht( | pht( | ||||
'Request parameter %s does not specify a valid client application.', | 'Request parameter %s does not specify a valid client application.', | ||||
phutil_tag('strong', array(), 'client_id'))); | phutil_tag('strong', array(), 'client_id'))); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | public function handleRequest(AphrontRequest $request) { | ||||
} | } | ||||
// Here, we're confirming authorization for the application. | // Here, we're confirming authorization for the application. | ||||
if ($authorization) { | if ($authorization) { | ||||
$desired_scopes = array_merge($scope, $authorization->getScope()); | $desired_scopes = array_merge($scope, $authorization->getScope()); | ||||
} else { | } else { | ||||
$desired_scopes = $scope; | $desired_scopes = $scope; | ||||
} | } | ||||
if (!PhabricatorOAuthServerScope::validateScopesDict($desired_scopes)) { | if (!PhabricatorOAuthServerScope::validateScopesDict($desired_scopes)) { | ||||
return $this->buildErrorResponse( | return $this->buildErrorResponse( | ||||
'invalid_scope', | 'invalid_scope', | ||||
pht('Invalid Scope'), | pht('Invalid Scope'), | ||||
pht('The requested scope is invalid, unknown, or malformed.')); | pht('The requested scope is invalid, unknown, or malformed.')); | ||||
} | } | ||||
$form = id(new AphrontFormView()) | $form = id(new AphrontFormView()) | ||||
Show All 9 Lines | public function handleRequest(AphrontRequest $request) { | ||||
$cancel_msg = pht('The user declined to authorize this application.'); | $cancel_msg = pht('The user declined to authorize this application.'); | ||||
$cancel_uri = $this->addQueryParams( | $cancel_uri = $this->addQueryParams( | ||||
$uri, | $uri, | ||||
array( | array( | ||||
'error' => 'access_denied', | 'error' => 'access_denied', | ||||
'error_description' => $cancel_msg, | 'error_description' => $cancel_msg, | ||||
)); | )); | ||||
$dialog = id(new AphrontDialogView()) | return $this->newDialog() | ||||
->setUser($viewer) | ->setShortTitle(pht('Authorize Access')) | ||||
->setTitle(pht('Authorize "%s"?', $name)) | ->setTitle(pht('Authorize "%s"?', $name)) | ||||
->setSubmitURI($request->getRequestURI()->getPath()) | ->setSubmitURI($request->getRequestURI()->getPath()) | ||||
->setWidth(AphrontDialogView::WIDTH_FORM) | ->setWidth(AphrontDialogView::WIDTH_FORM) | ||||
->appendParagraph( | ->appendParagraph( | ||||
pht( | pht( | ||||
'Do you want to authorize the external application "%s" to '. | 'Do you want to authorize the external application "%s" to '. | ||||
'access your Phabricator account data, including your primary '. | 'access your Phabricator account data, including your primary '. | ||||
'email address?', | 'email address?', | ||||
phutil_tag('strong', array(), $name))) | phutil_tag('strong', array(), $name))) | ||||
->appendChild($form->buildLayoutView()) | ->appendChild($form->buildLayoutView()) | ||||
->addSubmitButton(pht('Authorize Access')) | ->addSubmitButton(pht('Authorize Access')) | ||||
->addCancelButton((string)$cancel_uri, pht('Do Not Authorize')); | ->addCancelButton((string)$cancel_uri, pht('Do Not Authorize')); | ||||
return id(new AphrontDialogResponse())->setDialog($dialog); | |||||
} | } | ||||
private function buildErrorResponse($code, $title, $message) { | private function buildErrorResponse($code, $title, $message) { | ||||
$viewer = $this->getRequest()->getUser(); | $viewer = $this->getRequest()->getUser(); | ||||
$dialog = id(new AphrontDialogView()) | return $this->newDialog() | ||||
->setUser($viewer) | |||||
->setTitle(pht('OAuth: %s', $title)) | ->setTitle(pht('OAuth: %s', $title)) | ||||
->appendParagraph($message) | ->appendParagraph($message) | ||||
->appendParagraph( | ->appendParagraph( | ||||
pht('OAuth Error Code: %s', phutil_tag('tt', array(), $code))) | pht('OAuth Error Code: %s', phutil_tag('tt', array(), $code))) | ||||
->addCancelButton('/', pht('Alas!')); | ->addCancelButton('/', pht('Alas!')); | ||||
return id(new AphrontDialogResponse())->setDialog($dialog); | |||||
} | } | ||||
private function addQueryParams(PhutilURI $uri, array $params) { | private function addQueryParams(PhutilURI $uri, array $params) { | ||||
$full_uri = clone $uri; | $full_uri = clone $uri; | ||||
foreach ($params as $key => $value) { | foreach ($params as $key => $value) { | ||||
if (strlen($value)) { | if (strlen($value)) { | ||||
$full_uri->setQueryParam($key, $value); | $full_uri->setQueryParam($key, $value); | ||||
} | } | ||||
} | } | ||||
return $full_uri; | return $full_uri; | ||||
} | } | ||||
} | } |