Path: blob/master/src/applications/oauthserver/controller/PhabricatorOAuthServerTokenController.php
12242 views
<?php12final class PhabricatorOAuthServerTokenController3extends PhabricatorOAuthServerController {45public function shouldRequireLogin() {6return false;7}89public function shouldAllowRestrictedParameter($parameter_name) {10if ($parameter_name == 'code') {11return true;12}13return parent::shouldAllowRestrictedParameter($parameter_name);14}1516public function handleRequest(AphrontRequest $request) {17$grant_type = $request->getStr('grant_type');18$code = $request->getStr('code');19$redirect_uri = $request->getStr('redirect_uri');20$response = new PhabricatorOAuthResponse();21$server = new PhabricatorOAuthServer();2223$client_id_parameter = $request->getStr('client_id');24$client_id_header = idx($_SERVER, 'PHP_AUTH_USER');25if (strlen($client_id_parameter) && strlen($client_id_header)) {26if ($client_id_parameter !== $client_id_header) {27throw new Exception(28pht(29'Request included a client_id parameter and an "Authorization" '.30'header with a username, but the values "%s" and "%s") disagree. '.31'The values must match.',32$client_id_parameter,33$client_id_header));34}35}3637$client_secret_parameter = $request->getStr('client_secret');38$client_secret_header = idx($_SERVER, 'PHP_AUTH_PW');39if (strlen($client_secret_parameter)) {40// If the `client_secret` parameter is present, prefer parameters.41$client_phid = $client_id_parameter;42$client_secret = $client_secret_parameter;43} else {44// Otherwise, read values from the "Authorization" header.45$client_phid = $client_id_header;46$client_secret = $client_secret_header;47}4849if ($grant_type != 'authorization_code') {50$response->setError('unsupported_grant_type');51$response->setErrorDescription(52pht(53'Only %s %s is supported.',54'grant_type',55'authorization_code'));56return $response;57}5859if (!$code) {60$response->setError('invalid_request');61$response->setErrorDescription(pht('Required parameter code missing.'));62return $response;63}6465if (!$client_phid) {66$response->setError('invalid_request');67$response->setErrorDescription(68pht(69'Required parameter %s missing.',70'client_id'));71return $response;72}7374if (!$client_secret) {75$response->setError('invalid_request');76$response->setErrorDescription(77pht(78'Required parameter %s missing.',79'client_secret'));80return $response;81}8283// one giant try / catch around all the exciting database stuff so we84// can return a 'server_error' response if something goes wrong!85try {86$auth_code = id(new PhabricatorOAuthServerAuthorizationCode())87->loadOneWhere('code = %s',88$code);89if (!$auth_code) {90$response->setError('invalid_grant');91$response->setErrorDescription(92pht(93'Authorization code %s not found.',94$code));95return $response;96}9798// if we have an auth code redirect URI, there must be a redirect_uri99// in the request and it must match the auth code redirect uri *exactly*100$auth_code_redirect_uri = $auth_code->getRedirectURI();101if ($auth_code_redirect_uri) {102$auth_code_redirect_uri = new PhutilURI($auth_code_redirect_uri);103$redirect_uri = new PhutilURI($redirect_uri);104if (!$redirect_uri->getDomain() ||105$redirect_uri != $auth_code_redirect_uri) {106$response->setError('invalid_grant');107$response->setErrorDescription(108pht(109'Redirect URI in request must exactly match redirect URI '.110'from authorization code.'));111return $response;112}113} else if ($redirect_uri) {114$response->setError('invalid_grant');115$response->setErrorDescription(116pht(117'Redirect URI in request and no redirect URI in authorization '.118'code. The two must exactly match.'));119return $response;120}121122$client = id(new PhabricatorOAuthServerClient())123->loadOneWhere('phid = %s', $client_phid);124if (!$client) {125$response->setError('invalid_client');126$response->setErrorDescription(127pht(128'Client with %s %s not found.',129'client_id',130$client_phid));131return $response;132}133134if ($client->getIsDisabled()) {135$response->setError('invalid_client');136$response->setErrorDescription(137pht(138'OAuth application "%s" has been disabled.',139$client->getName()));140141return $response;142}143144$server->setClient($client);145146$user_phid = $auth_code->getUserPHID();147$user = id(new PhabricatorUser())148->loadOneWhere('phid = %s', $user_phid);149if (!$user) {150$response->setError('invalid_grant');151$response->setErrorDescription(152pht(153'User with PHID %s not found.',154$user_phid));155return $response;156}157$server->setUser($user);158159$test_code = new PhabricatorOAuthServerAuthorizationCode();160$test_code->setClientSecret($client_secret);161$test_code->setClientPHID($client_phid);162$is_good_code = $server->validateAuthorizationCode(163$auth_code,164$test_code);165if (!$is_good_code) {166$response->setError('invalid_grant');167$response->setErrorDescription(168pht(169'Invalid authorization code %s.',170$code));171return $response;172}173174$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();175$access_token = $server->generateAccessToken();176$auth_code->delete();177unset($unguarded);178$result = array(179'access_token' => $access_token->getToken(),180'token_type' => 'Bearer',181);182return $response->setContent($result);183} catch (Exception $e) {184$response->setError('server_error');185$response->setErrorDescription(186pht(187'The authorization server encountered an unexpected condition '.188'which prevented it from fulfilling the request.'));189return $response;190}191}192193}194195196