/** * Grant or deny a requested access token. * This would be called from the "/token" endpoint as defined in the spec. * Obviously, you can call your endpoint whatever you want. * * @param $request - OAuth2_Request * Request object to grant access token * @param $grantType - mixed * OAuth2_GrantTypeInterface instance or one of the grant types configured in the constructor * * @throws InvalidArgumentException * @throws LogicException * * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-4 * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-10.6 * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-4.1.3 * * @ingroup oauth2_section_4 */ public function grantAccessToken(OAuth2_Request $request, $grantType = null) { if (!isset($this->storage['client_credentials'])) { throw new LogicException('You must configure the server with client_credentials storage (setClientCredentialsStorage) in order to use this function'); } if (!$grantType instanceof OAuth2_GrantTypeInterface) { if (is_null($grantType)) { if (!($grantType = $request->parameter('grant_type'))) { $this->response = new OAuth2_Response_Error(400, 'invalid_request', 'The grant type was not specified in the request'); return null; } } else { if (!is_string($grantType)) { throw new InvalidArgumentException('parameter $grantType must be an instance of OAuth2_GrantTypeInterface, a string representing a configured grant type, or null to pull grant type from request'); } } if (!isset($this->grantTypes[$grantType])) { /* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */ $this->response = new OAuth2_Response_Error(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantType)); return null; } $grantType = $this->grantTypes[$grantType]; } if (!($clientData = $this->getClientCredentials($request))) { return null; } if (!isset($clientData['client_id']) || !isset($clientData['client_secret'])) { throw new LogicException('the clientData array must have "client_id" and "client_secret" values set. Use getClientCredentials()'); } if ($this->storage['client_credentials']->checkClientCredentials($clientData['client_id'], $clientData['client_secret']) === false) { $this->response = new OAuth2_Response_Error(400, 'invalid_client', 'The client credentials are invalid'); return null; } if (!$this->storage['client_credentials']->checkRestrictedGrantType($clientData['client_id'], $grantType)) { $this->response = new OAuth2_Response_Error(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id'); return null; } /* TODO: Find a better way to handle grantTypes and their responses */ if (!$grantType->validateRequest($request)) { if ($grantType instanceof OAuth2_Response_ProviderInterface && ($response = $grantType->getResponse())) { $this->response = $response; } else { // create a default response $this->response = new OAuth2_Response_Error(400, 'invalid_request', sprintf('Invalid request for "%s" grant type', $grantType->getIdentifier())); } return null; } if (!($tokenData = $grantType->getTokenDataFromRequest($request))) { if ($grantType instanceof OAuth2_Response_ProviderInterface && ($response = $grantType->getResponse())) { $this->response = $response; } else { // create a default response $this->response = new OAuth2_Response_Error(400, 'invalid_grant', sprintf('Unable to retrieve token for "%s" grant type', $grantType->getIdentifier())); } return null; } if (!$grantType->validateTokenData($tokenData, $clientData)) { if ($grantType instanceof OAuth2_Response_ProviderInterface && ($response = $grantType->getResponse())) { $this->response = $response; } else { // create a default response $this->response = new OAuth2_Response_Error(400, 'invalid_grant', 'Token is no longer valid'); } return null; } if (!isset($tokenData["scope"])) { $tokenData["scope"] = null; } // Check scope, if provided if (isset($request->query['scope']) && (!is_array($tokenData) || !isset($tokenData["scope"]) || !$this->checkScope($request->query['scope'], $tokenData["scope"]))) { $this->response = new OAuth2_Response_Error(400, 'invalid_scope', 'An unsupported scope was requested.'); return null; } $user_id = isset($tokenData['user_id']) ? $tokenData['user_id'] : null; $token = $this->createAccessToken($clientData['client_id'], $user_id, $tokenData['scope']); $grantType->finishGrantRequest($token); return $token; }