diff options
author | Frédéric Guillot <fred@kanboard.net> | 2014-11-06 06:41:47 -0500 |
---|---|---|
committer | Frédéric Guillot <fred@kanboard.net> | 2014-11-06 06:41:47 -0500 |
commit | c80c15dcc33a70acc2b177691d33f088f8c2541e (patch) | |
tree | bc3e44e35b97b751c145cc5797a0faf356922244 /vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php | |
parent | c91ff61cdfa8b5eb76783927e5b8710f2a9f2601 (diff) |
Include all vendor files in the repo to be easier for people
Diffstat (limited to 'vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php')
-rw-r--r-- | vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php b/vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php new file mode 100644 index 00000000..57dc76f2 --- /dev/null +++ b/vendor/lusitanian/oauth/src/OAuth/OAuth2/Service/AbstractService.php @@ -0,0 +1,333 @@ +<?php + +namespace OAuth\OAuth2\Service; + +use OAuth\Common\Consumer\CredentialsInterface; +use OAuth\Common\Exception\Exception; +use OAuth\Common\Service\AbstractService as BaseAbstractService; +use OAuth\Common\Storage\TokenStorageInterface; +use OAuth\Common\Http\Exception\TokenResponseException; +use OAuth\Common\Http\Client\ClientInterface; +use OAuth\Common\Http\Uri\UriInterface; +use OAuth\OAuth2\Service\Exception\InvalidAuthorizationStateException; +use OAuth\OAuth2\Service\Exception\InvalidScopeException; +use OAuth\OAuth2\Service\Exception\MissingRefreshTokenException; +use OAuth\Common\Token\TokenInterface; +use OAuth\Common\Token\Exception\ExpiredTokenException; + +abstract class AbstractService extends BaseAbstractService implements ServiceInterface +{ + /** @const OAUTH_VERSION */ + const OAUTH_VERSION = 2; + + /** @var array */ + protected $scopes; + + /** @var UriInterface|null */ + protected $baseApiUri; + + /** @var bool */ + protected $stateParameterInAuthUrl; + + /** + * @param CredentialsInterface $credentials + * @param ClientInterface $httpClient + * @param TokenStorageInterface $storage + * @param array $scopes + * @param UriInterface|null $baseApiUri + * @param bool $stateParameterInAutUrl + * + * @throws InvalidScopeException + */ + public function __construct( + CredentialsInterface $credentials, + ClientInterface $httpClient, + TokenStorageInterface $storage, + $scopes = array(), + UriInterface $baseApiUri = null, + $stateParameterInAutUrl = false + ) { + parent::__construct($credentials, $httpClient, $storage); + $this->stateParameterInAuthUrl = $stateParameterInAutUrl; + + foreach ($scopes as $scope) { + if (!$this->isValidScope($scope)) { + throw new InvalidScopeException('Scope ' . $scope . ' is not valid for service ' . get_class($this)); + } + } + + $this->scopes = $scopes; + + $this->baseApiUri = $baseApiUri; + } + + /** + * {@inheritdoc} + */ + public function getAuthorizationUri(array $additionalParameters = array()) + { + $parameters = array_merge( + $additionalParameters, + array( + 'type' => 'web_server', + 'client_id' => $this->credentials->getConsumerId(), + 'redirect_uri' => $this->credentials->getCallbackUrl(), + 'response_type' => 'code', + ) + ); + + $parameters['scope'] = implode(' ', $this->scopes); + + if ($this->needsStateParameterInAuthUrl()) { + if (!isset($parameters['state'])) { + $parameters['state'] = $this->generateAuthorizationState(); + } + $this->storeAuthorizationState($parameters['state']); + } + + // Build the url + $url = clone $this->getAuthorizationEndpoint(); + foreach ($parameters as $key => $val) { + $url->addToQuery($key, $val); + } + + return $url; + } + + /** + * {@inheritdoc} + */ + public function requestAccessToken($code, $state = null) + { + if (null !== $state) { + $this->validateAuthorizationState($state); + } + + $bodyParams = array( + 'code' => $code, + 'client_id' => $this->credentials->getConsumerId(), + 'client_secret' => $this->credentials->getConsumerSecret(), + 'redirect_uri' => $this->credentials->getCallbackUrl(), + 'grant_type' => 'authorization_code', + ); + + $responseBody = $this->httpClient->retrieveResponse( + $this->getAccessTokenEndpoint(), + $bodyParams, + $this->getExtraOAuthHeaders() + ); + + $token = $this->parseAccessTokenResponse($responseBody); + $this->storage->storeAccessToken($this->service(), $token); + + return $token; + } + + /** + * Sends an authenticated API request to the path provided. + * If the path provided is not an absolute URI, the base API Uri (must be passed into constructor) will be used. + * + * @param string|UriInterface $path + * @param string $method HTTP method + * @param array $body Request body if applicable. + * @param array $extraHeaders Extra headers if applicable. These will override service-specific + * any defaults. + * + * @return string + * + * @throws ExpiredTokenException + * @throws Exception + */ + public function request($path, $method = 'GET', $body = null, array $extraHeaders = array()) + { + $uri = $this->determineRequestUriFromPath($path, $this->baseApiUri); + $token = $this->storage->retrieveAccessToken($this->service()); + + if ($token->getEndOfLife() !== TokenInterface::EOL_NEVER_EXPIRES + && $token->getEndOfLife() !== TokenInterface::EOL_UNKNOWN + && time() > $token->getEndOfLife() + ) { + throw new ExpiredTokenException( + sprintf( + 'Token expired on %s at %s', + date('m/d/Y', $token->getEndOfLife()), + date('h:i:s A', $token->getEndOfLife()) + ) + ); + } + + // add the token where it may be needed + if (static::AUTHORIZATION_METHOD_HEADER_OAUTH === $this->getAuthorizationMethod()) { + $extraHeaders = array_merge(array('Authorization' => 'OAuth ' . $token->getAccessToken()), $extraHeaders); + } elseif (static::AUTHORIZATION_METHOD_QUERY_STRING === $this->getAuthorizationMethod()) { + $uri->addToQuery('access_token', $token->getAccessToken()); + } elseif (static::AUTHORIZATION_METHOD_QUERY_STRING_V2 === $this->getAuthorizationMethod()) { + $uri->addToQuery('oauth2_access_token', $token->getAccessToken()); + } elseif (static::AUTHORIZATION_METHOD_QUERY_STRING_V3 === $this->getAuthorizationMethod()) { + $uri->addToQuery('apikey', $token->getAccessToken()); + } elseif (static::AUTHORIZATION_METHOD_HEADER_BEARER === $this->getAuthorizationMethod()) { + $extraHeaders = array_merge(array('Authorization' => 'Bearer ' . $token->getAccessToken()), $extraHeaders); + } + + $extraHeaders = array_merge($this->getExtraApiHeaders(), $extraHeaders); + + return $this->httpClient->retrieveResponse($uri, $body, $extraHeaders, $method); + } + + /** + * Accessor to the storage adapter to be able to retrieve tokens + * + * @return TokenStorageInterface + */ + public function getStorage() + { + return $this->storage; + } + + /** + * Refreshes an OAuth2 access token. + * + * @param TokenInterface $token + * + * @return TokenInterface $token + * + * @throws MissingRefreshTokenException + */ + public function refreshAccessToken(TokenInterface $token) + { + $refreshToken = $token->getRefreshToken(); + + if (empty($refreshToken)) { + throw new MissingRefreshTokenException(); + } + + $parameters = array( + 'grant_type' => 'refresh_token', + 'type' => 'web_server', + 'client_id' => $this->credentials->getConsumerId(), + 'client_secret' => $this->credentials->getConsumerSecret(), + 'refresh_token' => $refreshToken, + ); + + $responseBody = $this->httpClient->retrieveResponse( + $this->getAccessTokenEndpoint(), + $parameters, + $this->getExtraOAuthHeaders() + ); + $token = $this->parseAccessTokenResponse($responseBody); + $this->storage->storeAccessToken($this->service(), $token); + + return $token; + } + + /** + * Return whether or not the passed scope value is valid. + * + * @param string $scope + * + * @return bool + */ + public function isValidScope($scope) + { + $reflectionClass = new \ReflectionClass(get_class($this)); + + return in_array($scope, $reflectionClass->getConstants(), true); + } + + /** + * Check if the given service need to generate a unique state token to build the authorization url + * + * @return bool + */ + public function needsStateParameterInAuthUrl() + { + return $this->stateParameterInAuthUrl; + } + + /** + * Validates the authorization state against a given one + * + * @param string $state + * @throws InvalidAuthorizationStateException + */ + protected function validateAuthorizationState($state) + { + if ($this->retrieveAuthorizationState() !== $state) { + throw new InvalidAuthorizationStateException(); + } + } + + /** + * Generates a random string to be used as state + * + * @return string + */ + protected function generateAuthorizationState() + { + return md5(rand()); + } + + /** + * Retrieves the authorization state for the current service + * + * @return string + */ + protected function retrieveAuthorizationState() + { + return $this->storage->retrieveAuthorizationState($this->service()); + } + + /** + * Stores a given authorization state into the storage + * + * @param string $state + */ + protected function storeAuthorizationState($state) + { + $this->storage->storeAuthorizationState($this->service(), $state); + } + + /** + * Return any additional headers always needed for this service implementation's OAuth calls. + * + * @return array + */ + protected function getExtraOAuthHeaders() + { + return array(); + } + + /** + * Return any additional headers always needed for this service implementation's API calls. + * + * @return array + */ + protected function getExtraApiHeaders() + { + return array(); + } + + /** + * Parses the access token response and returns a TokenInterface. + * + * @abstract + * + * @param string $responseBody + * + * @return TokenInterface + * + * @throws TokenResponseException + */ + abstract protected function parseAccessTokenResponse($responseBody); + + /** + * Returns a class constant from ServiceInterface defining the authorization method used for the API + * Header is the sane default. + * + * @return int + */ + protected function getAuthorizationMethod() + { + return static::AUTHORIZATION_METHOD_HEADER_OAUTH; + } +} |