Example #1
0
 /**
  * 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(RequestInterface $request, 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);
         }
         LogMessage($request->request('upload_image'));
         LogMessage($contentType);
         if (!$request->files['Filedata']) {
             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 - RequestInterface
  * Request object to grant access token
  *
  * @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(RequestInterface $request, 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 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);
 }
Example #3
0
 public function getAccessTokenParameter(RequestInterface $request, ResponseInterface $response)
 {
     $headers = $request->headers('AUTHORIZATION');
     $methodsUsed = !empty($headers) + (bool) $request->query($this->config['token_param_name']) + (bool) $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+)/i', $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 (!in_array(strtolower($request->server('REQUEST_METHOD')), array('post', 'put'))) {
             $response->setError(400, 'invalid_request', 'When putting the token in the body, the method must be POST or PUT', '#section-2.2');
             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') {
             $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']);
     }
     return $request->query($this->config['token_param_name']);
 }
 /**
  * Revoke a refresh or access token. Returns true on success and when tokens are invalid
  *
  * Note: invalid tokens do not cause an error response since the client
  * cannot handle such an error in a reasonable way.  Moreover, the
  * purpose of the revocation request, invalidating the particular token,
  * is already achieved.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool|null
  */
 public function revokeToken(RequestInterface $request, ResponseInterface $response)
 {
     if (strtolower($request->server('REQUEST_METHOD')) != 'post') {
         $response->setError(405, 'invalid_request', 'The request method must be POST when revoking an access token', '#section-3.2');
         $response->addHttpHeaders(array('Allow' => 'POST'));
         return null;
     }
     $token_type_hint = $request->request('token_type_hint');
     if (!in_array($token_type_hint, array(null, 'access_token', 'refresh_token'), true)) {
         $response->setError(400, 'invalid_request', 'Token type hint must be either \'access_token\' or \'refresh_token\'');
         return null;
     }
     $token = $request->request('token');
     if ($token === null) {
         $response->setError(400, 'invalid_request', 'Missing token parameter to revoke');
         return null;
     }
     // @todo remove this check for v2.0
     if (!method_exists($this->accessToken, 'revokeToken')) {
         $class = get_class($this->accessToken);
         throw new \RuntimeException("AccessToken {$class} does not implement required revokeToken method");
     }
     $this->accessToken->revokeToken($token, $token_type_hint);
     return true;
 }
Example #5
0
 /**
  * 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 - RequestInterface
  * Request object to grant access token
  *
  * @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(RequestInterface $request, 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];
     /**
      * 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 ClientAssertionTypeInterface) {
         if (!$this->clientAssertionType->validateRequest($request, $response)) {
             return null;
         }
         $clientId = $this->clientAssertionType->getClientId();
     }
     /**
      * Retrieve the grant type information from the request
      * The GrantTypeInterface object handles all validation
      * If the object is an instance of ClientAssertionTypeInterface,
      * That logic is handled here as well
      */
     if (!$grantType->validateRequest($request, $response)) {
         return null;
     }
     if ($grantType instanceof ClientAssertionTypeInterface) {
         $clientId = $grantType->getClientId();
     } else {
         // 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 client can use the requested grant type
      */
     if (!$this->clientStorage->checkRestrictedGrantType($clientId, $grantTypeIdentifier)) {
         $response->setError(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id');
         return false;
     }
     /**
      * Validate the scope of the token
      *
      * requestedScope - the scope specified in the token request
      * availableScope - the scope associated with the grant type
      *  ex: in the case of the "Authorization Code" grant type,
      *  the scope is specified in the authorize request
      *
      * @see http://tools.ietf.org/html/rfc6749#section-3.3
      */
     $requestedScope = $this->scopeUtil->getScopeFromRequest($request);
     $availableScope = $grantType->getScope();
     if ($requestedScope) {
         // validate the requested scope
         if ($availableScope) {
             if (!$this->scopeUtil->checkScope($requestedScope, $availableScope)) {
                 $response->setError(400, 'invalid_scope', 'The scope requested is invalid for this request');
                 return null;
             }
         } else {
             // validate the client has access to this scope
             if ($clientScope = $this->clientStorage->getClientScope($clientId)) {
                 if (!$this->scopeUtil->checkScope($requestedScope, $clientScope)) {
                     $response->setError(400, 'invalid_scope', 'The scope requested is invalid for this client');
                     return false;
                 }
             } elseif (!$this->scopeUtil->scopeExists($requestedScope)) {
                 $response->setError(400, 'invalid_scope', 'An unsupported scope was requested');
                 return null;
             }
         }
     } elseif ($availableScope) {
         // use the scope associated with this grant type
         $requestedScope = $availableScope;
     } else {
         // use a globally-defined default scope
         $defaultScope = $this->scopeUtil->getDefaultScope($clientId);
         // "false" means default scopes are not allowed
         if (false === $defaultScope) {
             $response->setError(400, 'invalid_scope', 'This application requires you specify a scope parameter');
             return null;
         }
         $requestedScope = $defaultScope;
     }
     return $grantType->createAccessToken($this->accessToken, $clientId, $grantType->getUserId(), $requestedScope);
 }
Example #6
0
 /**
  * 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(RequestInterface $request, ResponseInterface $response)
 {
     $headers = $request->headers('AUTHORIZATION');
     /**
      * Ensure more than one method is not used for including an
      * access token
      *
      * @see http://tools.ietf.org/html/rfc6750#section-3.1
      */
     $methodsUsed = !empty($headers) + (bool) $request->query($this->config['token_param_name']) + (bool) $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 no authentication is provided, set the status code
      * to 401 and return no other error information
      *
      * @see http://tools.ietf.org/html/rfc6750#section-3.1
      */
     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 (!in_array(strtolower($request->server('REQUEST_METHOD')), array('post', 'put'))) {
             $response->setError(400, 'invalid_request', 'When putting the token in the body, the method must be POST or PUT', '#section-2.2');
             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']);
 }
 public function grantAccessToken(RequestInterface $request, 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;
     }
     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])) {
         $response->setError(400, 'unsupported_grant_type', sprintf('Grant type "%s" not supported', $grantTypeIdentifier));
         return null;
     }
     $grantType = $this->grantTypes[$grantTypeIdentifier];
     if (!$grantType instanceof ClientAssertionTypeInterface) {
         if (!$this->clientAssertionType->validateRequest($request, $response)) {
             return null;
         }
         $clientId = $this->clientAssertionType->getClientId();
     }
     if (!$grantType->validateRequest($request, $response)) {
         return null;
     }
     if ($grantType instanceof ClientAssertionTypeInterface) {
         $clientId = $grantType->getClientId();
     } else {
         // 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 client can use the requested grant type
      */
     if (!$this->clientStorage->checkRestrictedGrantType($clientId, $grantTypeIdentifier)) {
         $response->setError(400, 'unauthorized_client', 'The grant type is unauthorized for this client_id');
         return false;
     }
     $requestedScope = $this->scopeUtil->getScopeFromRequest($request);
     $availableScope = $grantType->getScope();
     if ($requestedScope) {
         // validate the requested scope
         if ($availableScope) {
             if (!$this->scopeUtil->checkScope($requestedScope, $availableScope)) {
                 $response->setError(400, 'invalid_scope', 'The scope requested is invalid for this request');
                 return null;
             }
         } else {
             // validate the client has access to this scope
             if ($clientScope = $this->clientStorage->getClientScope($clientId)) {
                 if (!$this->scopeUtil->checkScope($requestedScope, $clientScope)) {
                     $response->setError(400, 'invalid_scope', 'The scope requested is invalid for this client');
                     return false;
                 }
             } elseif (!$this->scopeUtil->scopeExists($requestedScope)) {
                 $response->setError(400, 'invalid_scope', 'An unsupported scope was requested');
                 return null;
             }
         }
     } elseif ($availableScope) {
         // use the scope associated with this grant type
         $requestedScope = $availableScope;
     } else {
         // use a globally-defined default scope
         $defaultScope = $this->scopeUtil->getDefaultScope($clientId);
         // "false" means default scopes are not allowed
         if (false === $defaultScope) {
             $response->setError(400, 'invalid_scope', 'This application requires you specify a scope parameter');
             return null;
         }
         $requestedScope = $defaultScope;
     }
     return $grantType->createAccessToken($this->accessToken, $clientId, $grantType->getUserId(), $requestedScope);
 }