Пример #1
0
 /**
  * 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 $inputData - The draft specifies that the parameters should be
  * retrieved from POST, but you can override to whatever method you like.
  * @throws OAuth2ServerException
  * 
  * @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(array $inputData = NULL, array $authHeaders = NULL)
 {
     $filters = array("grant_type" => array("filter" => FILTER_VALIDATE_REGEXP, "options" => array("regexp" => self::GRANT_TYPE_REGEXP), "flags" => FILTER_REQUIRE_SCALAR), "scope" => array("flags" => FILTER_REQUIRE_SCALAR), "code" => array("flags" => FILTER_REQUIRE_SCALAR), "redirect_uri" => array("filter" => FILTER_SANITIZE_URL), "username" => array("flags" => FILTER_REQUIRE_SCALAR), "password" => array("flags" => FILTER_REQUIRE_SCALAR), "refresh_token" => array("flags" => FILTER_REQUIRE_SCALAR));
     // Input data by default can be either POST or GET
     if (!isset($inputData)) {
         $inputData = $_SERVER['REQUEST_METHOD'] == 'POST' ? $_POST : $_GET;
     }
     // Basic authorization header
     $authHeaders = isset($authHeaders) ? $authHeaders : $this->getAuthorizationHeader();
     // Filter input data
     $input = filter_var_array($inputData, $filters);
     // Grant Type must be specified.
     if (!$input["grant_type"]) {
         throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing');
     }
     // Authorize the client
     $client = $this->getClientCredentials($inputData, $authHeaders);
     if ($this->storage->checkClientCredentials($client[0], $client[1]) === FALSE) {
         throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_CLIENT, 'The client credentials are invalid');
     }
     if (!$this->storage->checkRestrictedGrantType($client[0], $input["grant_type"])) {
         throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNAUTHORIZED_CLIENT, 'The grant type is unauthorized for this client_id');
     }
     // Do the granting
     switch ($input["grant_type"]) {
         case self::GRANT_TYPE_AUTH_CODE:
             if (!$this->storage instanceof IOAuth2GrantCode) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             if (!$input["code"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Missing parameter. "code" is required');
             }
             if ($this->getVariable(self::CONFIG_ENFORCE_INPUT_REDIRECT) && !$input["redirect_uri"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, "The redirect URI parameter is required.");
             }
             $stored = $this->storage->getAuthCode($input["code"]);
             // Check the code exists
             if ($stored === NULL || $client[0] != $stored["client_id"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT, "Refresh token doesn't exist or is invalid for the client");
             }
             // Validate the redirect URI. If a redirect URI has been provided on input, it must be validated
             if ($input["redirect_uri"] && !$this->validateRedirectUri($input["redirect_uri"], $stored["redirect_uri"])) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_REDIRECT_URI_MISMATCH, "The redirect URI is missing or do not match");
             }
             if ($stored["expires"] < time()) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT, "The authorization code has expired");
             }
             break;
         case self::GRANT_TYPE_USER_CREDENTIALS:
             if (!$this->storage instanceof IOAuth2GrantUser) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             if (!$input["username"] || !$input["password"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Missing parameters. "username" and "password" required');
             }
             $stored = $this->storage->checkUserCredentials($client[0], $input["username"], $input["password"]);
             if ($stored === FALSE) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT);
             }
             break;
         case self::GRANT_TYPE_CLIENT_CREDENTIALS:
             if (!$this->storage instanceof IOAuth2GrantClient) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             if (empty($client[1])) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_CLIENT, 'The client_secret is mandatory for the "client_credentials" grant type');
             }
             // NB: We don't need to check for $stored==false, because it was checked above already
             $stored = $this->storage->checkClientCredentialsGrant($client[0], $client[1]);
             break;
         case self::GRANT_TYPE_REFRESH_TOKEN:
             if (!$this->storage instanceof IOAuth2RefreshTokens) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             if (!$input["refresh_token"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'No "refresh_token" parameter found');
             }
             $stored = $this->storage->getRefreshToken($input["refresh_token"]);
             if ($stored === NULL || $client[0] != $stored["client_id"]) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT, 'Invalid refresh token');
             }
             if ($stored["expires"] < time()) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT, 'Refresh token has expired');
             }
             // store the refresh token locally so we can delete it when a new refresh token is generated
             $this->oldRefreshToken = $stored["refresh_token"];
             break;
         case self::GRANT_TYPE_IMPLICIT:
             /* TODO: NOT YET IMPLEMENTED */
             throw new OAuth2ServerException('501 Not Implemented', 'This OAuth2 library is not yet complete. This functionality is not implemented yet.');
             if (!$this->storage instanceof IOAuth2GrantImplicit) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             break;
             // Extended grant types:
         // Extended grant types:
         case filter_var($input["grant_type"], FILTER_VALIDATE_URL):
             if (!$this->storage instanceof IOAuth2GrantExtension) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNSUPPORTED_GRANT_TYPE);
             }
             $uri = filter_var($input["grant_type"], FILTER_VALIDATE_URL);
             $stored = $this->storage->checkGrantExtension($uri, $inputData, $authHeaders);
             if ($stored === FALSE) {
                 throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_GRANT);
             }
             break;
         default:
             throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing');
     }
     if (!isset($stored["scope"])) {
         $stored["scope"] = NULL;
     }
     // Check scope, if provided
     if ($input["scope"] && (!is_array($stored) || !isset($stored["scope"]) || !$this->checkScope($input["scope"], $stored["scope"]))) {
         throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_SCOPE, 'An unsupported scope was requested.');
     }
     $user_id = isset($stored['user_id']) ? $stored['user_id'] : null;
     $token = $this->createAccessToken($client[0], $user_id, $stored['scope']);
     // Send response
     $this->sendJsonHeaders();
     echo json_encode($token);
 }