/**
  * Grant or deny a requested access token.
  * This would be called from the "/token" endpoint as defined in the spec.
  * You can call your endpoint whatever you want.
  *
  * @param $request - OAuth2_RequestInterface
  * 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/rfc6749#section-4
  * @see http://tools.ietf.org/html/rfc6749#section-10.6
  * @see http://tools.ietf.org/html/rfc6749#section-4.1.3
  *
  * @ingroup oauth2_section_4
  */
 public function grantAccessToken(OAuth2_RequestInterface $request, OAuth2_ResponseInterface $response)
 {
     if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
         $response->setError(405, 'invalid_request', 'The request method must be POST when requesting an access token', '#section-3.2');
         $response->addHttpHeaders(array('Allow' => 'POST'));
         return null;
     }
     /* Determine grant type from request
      * and validate the request for that grant type
      */
     if (!($grantTypeIdentifier = $request->request('grant_type'))) {
         $response->setError(400, 'invalid_request', 'The grant type was not specified in the request');
         return null;
     }
     if (!isset($this->grantTypes[$grantTypeIdentifier])) {
         /* TODO: If this is an OAuth2 supported grant type that we have chosen not to implement, throw a 501 Not Implemented instead */
         $response->setError(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantTypeIdentifier));
         return null;
     }
     $grantType = $this->grantTypes[$grantTypeIdentifier];
     if (!$grantType->validateRequest($request, $response)) {
         return null;
     }
     /* Retrieve the client information from the request
      * ClientAssertionTypes allow for grant types which also assert the client data
      * in which case ClientAssertion is handled in the validateRequest method
      *
      * @see OAuth2_GrantType_JWTBearer
      * @see OAuth2_GrantType_ClientCredentials
      */
     if ($grantType instanceof OAuth2_ClientAssertionTypeInterface) {
         $clientId = $grantType->getClientId();
     } else {
         if (!$this->clientAssertionType->validateRequest($request, $response)) {
             return null;
         }
         $clientId = $this->clientAssertionType->getClientId();
         // validate the Client ID (if applicable)
         if (!is_null($storedClientId = $grantType->getClientId()) && $storedClientId != $clientId) {
             $response->setError(400, 'invalid_grant', sprintf('%s doesn\'t exist or is invalid for the client', $grantTypeIdentifier));
             return null;
         }
     }
     /*
      * Validate the scope of the token
      * If the grant type returns a value for the scope,
      * this value must be verified with the scope being requested
      */
     $availableScope = $grantType->getScope();
     if (!($requestedScope = $this->scopeUtil->getScopeFromRequest($request))) {
         $requestedScope = $availableScope ? $availableScope : $this->scopeUtil->getDefaultScope();
     }
     if ($requestedScope && !$this->scopeUtil->scopeExists($requestedScope, $clientId) || $availableScope && !$this->scopeUtil->checkScope($requestedScope, $availableScope)) {
         $response->setError(400, 'invalid_scope', 'An unsupported scope was requested');
         return null;
     }
     return $grantType->createAccessToken($this->accessToken, $clientId, $grantType->getUserId(), $requestedScope);
 }
 /**
  * This is a convenience function that can be used to get the token, which can then
  * be passed to getAccessTokenData(). The constraints specified by the draft are
  * attempted to be adheared to in this method.
  *
  * As per the Bearer spec (draft 8, section 2) - there are three ways for a client
  * to specify the bearer token, in order of preference: Authorization Header,
  * POST and GET.
  *
  * NB: Resource servers MUST accept tokens via the Authorization scheme
  * (http://tools.ietf.org/html/rfc6750#section-2).
  *
  * @todo Should we enforce TLS/SSL in this function?
  *
  * @see http://tools.ietf.org/html/rfc6750#section-2.1
  * @see http://tools.ietf.org/html/rfc6750#section-2.2
  * @see http://tools.ietf.org/html/rfc6750#section-2.3
  *
  * Old Android version bug (at least with version 2.2)
  * @see http://code.google.com/p/android/issues/detail?id=6684
  *
  */
 public function getAccessTokenParameter(OAuth2_RequestInterface $request, OAuth2_ResponseInterface $response)
 {
     $headers = $request->headers('AUTHORIZATION');
     // Check that exactly one method was used
     $methodsUsed = !empty($headers) + !is_null($request->query($this->config['token_param_name'])) + !is_null($request->request($this->config['token_param_name']));
     if ($methodsUsed > 1) {
         $response->setError(400, 'invalid_request', 'Only one method may be used to authenticate at a time (Auth header, GET or POST)');
         return null;
     }
     if ($methodsUsed == 0) {
         $response->setStatusCode(401);
         return null;
     }
     // HEADER: Get the access token from the header
     if (!empty($headers)) {
         if (!preg_match('/' . $this->config['token_bearer_header_name'] . '\\s(\\S+)/', $headers, $matches)) {
             $response->setError(400, 'invalid_request', 'Malformed auth header');
             return null;
         }
         return $matches[1];
     }
     if ($request->request($this->config['token_param_name'])) {
         // POST: Get the token from POST data
         if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
             $response->setError(400, 'invalid_request', 'When putting the token in the body, the method must be POST');
             return null;
         }
         $contentType = $request->server('CONTENT_TYPE');
         if (false !== ($pos = strpos($contentType, ';'))) {
             $contentType = substr($contentType, 0, $pos);
         }
         if ($contentType !== null && $contentType != 'application/x-www-form-urlencoded') {
             // IETF specifies content-type. NB: Not all webservers populate this _SERVER variable
             // @see http://tools.ietf.org/html/rfc6750#section-2.2
             $response->setError(400, 'invalid_request', 'The content type for POST requests must be "application/x-www-form-urlencoded"');
             return null;
         }
         return $request->request($this->config['token_param_name']);
     }
     // GET method
     return $request->query($this->config['token_param_name']);
 }
 /**
  * Grant or deny a requested access token.
  * This would be called from the "/token" endpoint as defined in the spec.
  * You can call your endpoint whatever you want.
  *
  * @param $request - OAuth2_RequestInterface
  * 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/rfc6749#section-4
  * @see http://tools.ietf.org/html/rfc6749#section-10.6
  * @see http://tools.ietf.org/html/rfc6749#section-4.1.3
  *
  * @ingroup oauth2_section_4
  */
 public function grantAccessToken(OAuth2_RequestInterface $request)
 {
     if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
         $this->response = new OAuth2_Response_Error(400, 'invalid_request', 'The request method must be POST when requesting an access token', 'http://tools.ietf.org/html/rfc6749#section-3.2');
         return null;
     }
     // Determine grant type from request
     if (!($grantType = $request->request('grant_type'))) {
         $this->response = new OAuth2_Response_Error(400, 'invalid_request', 'The grant type was not specified in the request');
         return null;
     }
     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];
     // Hack to see if clientAssertionType is part of the grant type
     // this should change, but right now changing it will break BC
     $clientAssertionType = $grantType instanceof OAuth2_ClientAssertionTypeInterface ? $grantType : $this->clientAssertionType;
     $clientData = $clientAssertionType->getClientDataFromRequest($request);
     if (!$clientData || !$clientAssertionType->validateClientData($clientData, $grantType->getQuerystringIdentifier())) {
         $this->response = $this->getObjectResponse($clientAssertionType, new OAuth2_Response_Error(400, 'invalid_request', 'Unable to verify client'));
         return null;
     }
     // validate the request for the token
     if (!$grantType->validateRequest($request)) {
         $this->response = $this->getObjectResponse($grantType, new OAuth2_Response_Error(400, 'invalid_request', sprintf('Invalid request for "%s" grant type', $grantType->getQuerystringIdentifier())));
         return null;
     }
     if (!($tokenData = $grantType->getTokenDataFromRequest($request))) {
         $this->response = $this->getObjectResponse($grantType, new OAuth2_Response_Error(400, 'invalid_grant', sprintf('Unable to retrieve token for "%s" grant type', $grantType->getQuerystringIdentifier())));
         return null;
     }
     if (!$grantType->validateTokenData($tokenData, $clientData)) {
         $this->response = $this->getObjectResponse($grantType, new OAuth2_Response_Error(400, 'invalid_grant', 'Token is no longer valid'));
         return null;
     }
     if (!isset($tokenData["scope"])) {
         $tokenData["scope"] = $this->scopeUtil->getDefaultScope();
     }
     $scope = $this->scopeUtil->getScopeFromRequest($request);
     // Check scope, if provided
     if (!is_null($scope) && !$this->scopeUtil->checkScope($scope, $tokenData["scope"])) {
         $this->response = new OAuth2_Response_Error(400, 'invalid_scope', 'An unsupported scope was requested.');
         return null;
     }
     $tokenData['user_id'] = isset($tokenData['user_id']) ? $tokenData['user_id'] : null;
     return $grantType->createAccessToken($this->accessToken, $clientData, $tokenData);
 }