├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml.dist └── src └── OAuth ├── Common ├── Consumer │ ├── Credentials.php │ └── CredentialsInterface.php ├── Exception │ └── Exception.php ├── Http │ ├── Client │ │ ├── AbstractClient.php │ │ ├── ClientInterface.php │ │ ├── CurlClient.php │ │ └── StreamClient.php │ ├── Exception │ │ └── TokenResponseException.php │ └── Uri │ │ ├── Uri.php │ │ ├── UriFactory.php │ │ ├── UriFactoryInterface.php │ │ └── UriInterface.php ├── Service │ ├── AbstractService.php │ └── ServiceInterface.php ├── Storage │ ├── Exception │ │ ├── AuthorizationStateNotFoundException.php │ │ ├── StorageException.php │ │ └── TokenNotFoundException.php │ ├── Memory.php │ ├── Redis.php │ ├── Session.php │ ├── SymfonySession.php │ └── TokenStorageInterface.php └── Token │ ├── AbstractToken.php │ ├── Exception │ └── ExpiredTokenException.php │ └── TokenInterface.php ├── Helper └── Example.php ├── OAuth1 ├── Service │ ├── AbstractService.php │ ├── BitBucket.php │ ├── Etsy.php │ ├── FitBit.php │ ├── FiveHundredPx.php │ ├── Flickr.php │ ├── QuickBooks.php │ ├── Redmine.php │ ├── ScoopIt.php │ ├── ServiceInterface.php │ ├── Tumblr.php │ ├── Twitter.php │ └── Yahoo.php ├── Signature │ ├── Exception │ │ └── UnsupportedHashAlgorithmException.php │ ├── Signature.php │ └── SignatureInterface.php └── Token │ ├── StdOAuth1Token.php │ └── TokenInterface.php ├── OAuth2 ├── Service │ ├── AbstractService.php │ ├── Amazon.php │ ├── BattleNet.php │ ├── Bitly.php │ ├── Bitrix24.php │ ├── Box.php │ ├── Buffer.php │ ├── Dailymotion.php │ ├── Deezer.php │ ├── Delicious.php │ ├── DeviantArt.php │ ├── Dropbox.php │ ├── EveOnline.php │ ├── Exception │ │ ├── InvalidAccessTypeException.php │ │ ├── InvalidAuthorizationStateException.php │ │ ├── InvalidScopeException.php │ │ └── MissingRefreshTokenException.php │ ├── Facebook.php │ ├── Foursquare.php │ ├── GitHub.php │ ├── Google.php │ ├── Harvest.php │ ├── Heroku.php │ ├── Hubic.php │ ├── Instagram.php │ ├── JawboneUP.php │ ├── Linkedin.php │ ├── Mailchimp.php │ ├── Microsoft.php │ ├── Mondo.php │ ├── Nest.php │ ├── Netatmo.php │ ├── ParrotFlowerPower.php │ ├── Paypal.php │ ├── Pinterest.php │ ├── Pocket.php │ ├── Reddit.php │ ├── RunKeeper.php │ ├── Salesforce.php │ ├── ServiceInterface.php │ ├── SoundCloud.php │ ├── Spotify.php │ ├── Strava.php │ ├── Stripe.php │ ├── Ustream.php │ ├── Vimeo.php │ ├── Vkontakte.php │ ├── Xing.php │ ├── Yahoo.php │ ├── Yammer.php │ └── Yandex.php └── Token │ ├── StdOAuth2Token.php │ └── TokenInterface.php └── ServiceFactory.php /LICENSE: -------------------------------------------------------------------------------- 1 | (c) 2013 David Desberg 2 | Contributions (c) 2013 Pieter Hordijk 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHPoAuthLib 2 | =========== 3 | **NOTE: I'm looking for someone who could help to maintain this package alongside me, just because I don't have a ton of time to devote to it. However, I'm still going to keep trying to pay attention to PRs, etc.** 4 | 5 | PHPoAuthLib provides oAuth support in PHP 7.2+ and is very easy to integrate with any project which requires an oAuth client. 6 | 7 | [![Build Status](https://travis-ci.org/Lusitanian/PHPoAuthLib.png?branch=master)](https://travis-ci.org/Lusitanian/PHPoAuthLib) 8 | [![Code Coverage](https://scrutinizer-ci.com/g/Lusitanian/PHPoAuthLib/badges/coverage.png?s=a0a15bebfda49e79f9ce289b00c6dfebd18fc98e)](https://scrutinizer-ci.com/g/Lusitanian/PHPoAuthLib/) 9 | [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Lusitanian/PHPoAuthLib/badges/quality-score.png?s=c5976d2fefceb501f0d886c1a5bf087e69b44533)](https://scrutinizer-ci.com/g/Lusitanian/PHPoAuthLib/) 10 | [![Latest Stable Version](https://poser.pugx.org/lusitanian/oauth/v/stable.png)](https://packagist.org/packages/lusitanian/oauth) 11 | [![Total Downloads](https://poser.pugx.org/lusitanian/oauth/downloads.png)](https://packagist.org/packages/lusitanian/oauth) 12 | 13 | Installation 14 | ------------ 15 | This library can be found on [Packagist](https://packagist.org/packages/lusitanian/oauth). 16 | The recommended way to install this is through [composer](http://getcomposer.org). 17 | 18 | 19 | ```bash 20 | composer require lusitanian/oauth 21 | ``` 22 | 23 | Features 24 | -------- 25 | - PSR-4 26 | - Fully extensible in every facet. 27 | - You can implement any service with any custom requirements by extending the protocol version's `AbstractService` implementation. 28 | - You can use any HTTP client you desire, just create a class utilizing it which implements `OAuth\Common\Http\ClientInterface` (two implementations are included) 29 | - You can use any storage mechanism for tokens. By default, session, in-memory and Redis.io (requires PHPRedis) storage mechanisms are included. Implement additional mechanisms by implementing `OAuth\Common\Token\TokenStorageInterface`. 30 | 31 | Service support 32 | --------------- 33 | The library supports both oAuth 1.x and oAuth 2.0 compliant services. A list of currently implemented services can be found below. 34 | 35 | Included service implementations 36 | -------------------------------- 37 | - OAuth1 38 | - 500px 39 | - BitBucket 40 | - Etsy 41 | - FitBit 42 | - Flickr 43 | - QuickBooks 44 | - Scoop.it! 45 | - Tumblr 46 | - Twitter 47 | - Yahoo 48 | - OAuth2 49 | - Amazon 50 | - BitLy 51 | - Bitrix24 52 | - Box 53 | - Buffer 54 | - Dailymotion 55 | - Delicious 56 | - Deezer 57 | - DeviantArt 58 | - Dropbox 59 | - Eve Online 60 | - Facebook 61 | - Foursquare 62 | - GitHub 63 | - Google 64 | - Harvest 65 | - Heroku 66 | - Hubic 67 | - Instagram 68 | - Jawbone UP 69 | - LinkedIn 70 | - Mailchimp 71 | - Microsoft 72 | - Mondo 73 | - Nest 74 | - Netatmo 75 | - Parrot Flower Power 76 | - PayPal 77 | - Pinterest 78 | - Pocket 79 | - Reddit 80 | - RunKeeper 81 | - Salesforce 82 | - SoundCloud 83 | - Spotify 84 | - Strava 85 | - Stripe 86 | - Ustream 87 | - Vimeo 88 | - Vkontakte 89 | - Xing 90 | - Yahoo 91 | - Yammer 92 | - more to come! 93 | 94 | Examples 95 | -------- 96 | ```bash 97 | php -S localhost:8000 -t examples 98 | ``` 99 | Then point your browser to: 100 | ```text 101 | http://localhost:8000/ 102 | ``` 103 | 104 | 105 | Usage 106 | ------ 107 | For usage with complete auth flow, please see the examples. More in-depth documentation will come with release 1.0. 108 | 109 | Framework Integration 110 | --------------------- 111 | * Lithium: Sébastien Charrier has written [an adapter](https://github.com/scharrier/li3_socialauth) for the library. 112 | * Laravel 4: Dariusz Prząda has written [a service provider](https://github.com/artdarek/oauth-4-laravel) for the library. 113 | * Laravel 5: Valentin Ivaşcu ported Dariusz Prząda's Laravel 4 library to [Laravel 5](https://github.com/oriceon/oauth-5-laravel). 114 | * Symfony: Alexander Pinnecke has written [a Symfony Bundle](https://github.com/apinnecke/OAuthBundle) for the library. 115 | 116 | Extensions 117 | ---------- 118 | * Extract normalized user data from OAuth Services with the library [PHPoAuthUserData](https://github.com/Oryzone/PHPoAuthUserData) by Luciano Mammino 119 | 120 | Tests 121 | ------ 122 | ```bash 123 | composer tests 124 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lusitanian/oauth", 3 | "description": "PHP 7.2 oAuth 1/2 Library", 4 | "keywords": ["oauth", "authentication", "authorization", "security"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "David Desberg", 9 | "email": "david@daviddesberg.com" 10 | }, 11 | { 12 | "name": "Pieter Hordijk", 13 | "email": "info@pieterhordijk.com" 14 | }, 15 | { 16 | "name": "Elliot Chance", 17 | "email": "elliotchance@gmail.com" 18 | } 19 | ], 20 | "scripts" : { 21 | "tests" : [ 22 | "./vendor/bin/phpunit --color=always" 23 | ], 24 | "check" : [ 25 | "./vendor/bin/php-cs-fixer fix --ansi --dry-run --diff", 26 | "./vendor/bin/phpunit --color=always" 27 | ], 28 | "fix": [ 29 | "./vendor/bin/php-cs-fixer fix --ansi" 30 | ] 31 | }, 32 | "require": { 33 | "php": "^7.2 || 8.0.*" 34 | }, 35 | "require-dev": { 36 | "ext-dom": "*", 37 | "ext-curl": "*", 38 | "ext-json": "*", 39 | "symfony/http-foundation": "~2.1", 40 | "predis/predis": "0.8.*@dev", 41 | "squizlabs/php_codesniffer": "^3.5", 42 | "symfony/var-dumper": "^5.1", 43 | "symfony/finder": "^5.1", 44 | "phpunit/phpunit": "^8.5", 45 | "friendsofphp/php-cs-fixer": "^3.0" 46 | }, 47 | "suggest": { 48 | "symfony/http-foundation": "Allows using the Symfony Session storage backend.", 49 | "predis/predis": "Allows using the Redis storage backend.", 50 | "ext-openssl": "Allows for usage of secure connections with the stream-based HTTP client." 51 | }, 52 | "autoload": { 53 | "psr-4": { 54 | "OAuth\\": "src/OAuth" 55 | } 56 | }, 57 | "autoload-dev": { 58 | "psr-4": { 59 | "OAuthTest\\Unit\\": "tests/Unit", 60 | "OAuthTest\\Mocks\\": "tests/Mocks" 61 | } 62 | }, 63 | 64 | "extra": { 65 | "branch-alias": { 66 | "dev-master": "0.1-dev" 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | tests 9 | 10 | 11 | 12 | 13 | ./src/ 14 | 15 | src/OAuth/bootstrap.php 16 | src/OAuth/Common/Exception/Exception.php 17 | src/OAuth/Common/Http/Exception/TokenResponseException.php 18 | src/OAuth/Common/Storage/Exception/StorageException.php 19 | src/OAuth/Common/Storage/Exception/TokenNotFoundException.php 20 | src/OAuth/Common/Token/Exception/ExpiredTokenException.php 21 | src/OAuth/OAuth1/Signature/Exception/UnsupportedHashAlgorithmException.php 22 | src/OAuth/OAuth2/Service/Exception/InvalidScopeException.php 23 | src/OAuth/OAuth2/Service/Exception/MissingRefreshTokenException.php 24 | src/OAuth/OAuth2/Token/StdOAuth2Token.php 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/OAuth/Common/Consumer/Credentials.php: -------------------------------------------------------------------------------- 1 | consumerId = $consumerId; 33 | $this->consumerSecret = $consumerSecret; 34 | $this->callbackUrl = $callbackUrl; 35 | } 36 | 37 | /** 38 | * @return string 39 | */ 40 | public function getCallbackUrl() 41 | { 42 | return $this->callbackUrl; 43 | } 44 | 45 | /** 46 | * @return string 47 | */ 48 | public function getConsumerId() 49 | { 50 | return $this->consumerId; 51 | } 52 | 53 | /** 54 | * @return string 55 | */ 56 | public function getConsumerSecret() 57 | { 58 | return $this->consumerSecret; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/OAuth/Common/Consumer/CredentialsInterface.php: -------------------------------------------------------------------------------- 1 | userAgent = $userAgent; 33 | } 34 | 35 | /** 36 | * @param int $redirects Maximum redirects for client 37 | * 38 | * @return ClientInterface 39 | */ 40 | public function setMaxRedirects($redirects) 41 | { 42 | $this->maxRedirects = $redirects; 43 | 44 | return $this; 45 | } 46 | 47 | /** 48 | * @param int $timeout Request timeout time for client in seconds 49 | * 50 | * @return ClientInterface 51 | */ 52 | public function setTimeout($timeout) 53 | { 54 | $this->timeout = $timeout; 55 | 56 | return $this; 57 | } 58 | 59 | /** 60 | * @param array $headers 61 | */ 62 | public function normalizeHeaders($headers): array 63 | { 64 | $normalizeHeaders = []; 65 | foreach ($headers as $key => $val) { 66 | $val = ucfirst(strtolower($key)) . ': ' . $val; 67 | $normalizeHeaders[$key] = $val; 68 | } 69 | 70 | return $normalizeHeaders; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/OAuth/Common/Http/Client/ClientInterface.php: -------------------------------------------------------------------------------- 1 | value` pairs) to be passed to `curl_setopt`. 24 | * 25 | * @var array 26 | */ 27 | private $parameters = []; 28 | 29 | /** 30 | * Additional `curl_setopt` parameters. 31 | */ 32 | public function setCurlParameters(array $parameters): void 33 | { 34 | $this->parameters = $parameters; 35 | } 36 | 37 | /** 38 | * @param bool $force 39 | * 40 | * @return CurlClient 41 | */ 42 | public function setForceSSL3($force) 43 | { 44 | $this->forceSSL3 = $force; 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Any implementing HTTP providers should send a request to the provided endpoint with the parameters. 51 | * They should return, in string form, the response body and throw an exception on error. 52 | * 53 | * @param mixed $requestBody 54 | * @param string $method 55 | * 56 | * @return string 57 | */ 58 | public function retrieveResponse( 59 | UriInterface $endpoint, 60 | $requestBody, 61 | array $extraHeaders = [], 62 | $method = 'POST' 63 | ) { 64 | // Normalize method name 65 | $method = strtoupper($method); 66 | 67 | $extraHeaders = $this->normalizeHeaders($extraHeaders); 68 | 69 | if ($method === 'GET' && !empty($requestBody)) { 70 | throw new InvalidArgumentException('No body expected for "GET" request.'); 71 | } 72 | 73 | if (!isset($extraHeaders['Content-Type']) && $method === 'POST' && is_array($requestBody)) { 74 | $extraHeaders['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded'; 75 | } 76 | 77 | $extraHeaders['Host'] = 'Host: ' . $endpoint->getHost(); 78 | $extraHeaders['Connection'] = 'Connection: close'; 79 | 80 | $ch = curl_init(); 81 | 82 | curl_setopt($ch, CURLOPT_URL, $endpoint->getAbsoluteUri()); 83 | 84 | if ($method === 'POST' || $method === 'PUT') { 85 | if ($requestBody && is_array($requestBody)) { 86 | $requestBody = http_build_query($requestBody, '', '&'); 87 | } 88 | 89 | if ($method === 'PUT') { 90 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); 91 | } else { 92 | curl_setopt($ch, CURLOPT_POST, true); 93 | } 94 | 95 | curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody); 96 | } else { 97 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); 98 | } 99 | 100 | if ($this->maxRedirects > 0) { 101 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 102 | curl_setopt($ch, CURLOPT_MAXREDIRS, $this->maxRedirects); 103 | } 104 | 105 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); 106 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 107 | curl_setopt($ch, CURLOPT_HEADER, false); 108 | curl_setopt($ch, CURLOPT_HTTPHEADER, $extraHeaders); 109 | curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent); 110 | 111 | foreach ($this->parameters as $key => $value) { 112 | curl_setopt($ch, $key, $value); 113 | } 114 | 115 | $response = curl_exec($ch); 116 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 117 | 118 | if (false === $response) { 119 | $errNo = curl_errno($ch); 120 | $errStr = curl_error($ch); 121 | curl_close($ch); 122 | if (empty($errStr)) { 123 | throw new TokenResponseException('Failed to request resource.', $responseCode); 124 | } 125 | 126 | throw new TokenResponseException('cURL Error # ' . $errNo . ': ' . $errStr, $responseCode); 127 | } 128 | 129 | curl_close($ch); 130 | 131 | return $response; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/OAuth/Common/Http/Client/StreamClient.php: -------------------------------------------------------------------------------- 1 | normalizeHeaders($extraHeaders); 33 | 34 | if ($method === 'GET' && !empty($requestBody)) { 35 | throw new InvalidArgumentException('No body expected for "GET" request.'); 36 | } 37 | 38 | if (!isset($extraHeaders['Content-Type']) && $method === 'POST' && is_array($requestBody)) { 39 | $extraHeaders['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded'; 40 | } 41 | 42 | $host = 'Host: ' . $endpoint->getHost(); 43 | // Append port to Host if it has been specified 44 | if ($endpoint->hasExplicitPortSpecified()) { 45 | $host .= ':' . $endpoint->getPort(); 46 | } 47 | 48 | $extraHeaders['Host'] = $host; 49 | $extraHeaders['Connection'] = 'Connection: close'; 50 | 51 | if (is_array($requestBody)) { 52 | $requestBody = http_build_query($requestBody, '', '&'); 53 | } 54 | $extraHeaders['Content-length'] = 'Content-length: ' . strlen($requestBody); 55 | 56 | $context = $this->generateStreamContext($requestBody, $extraHeaders, $method); 57 | 58 | $level = error_reporting(0); 59 | $response = file_get_contents($endpoint->getAbsoluteUri(), false, $context); 60 | error_reporting($level); 61 | if (false === $response) { 62 | $lastError = error_get_last(); 63 | if (null === $lastError) { 64 | throw new TokenResponseException( 65 | 'Failed to request resource. HTTP Code: ' . 66 | ((isset($http_response_header[0])) ? $http_response_header[0] : 'No response') 67 | ); 68 | } 69 | 70 | throw new TokenResponseException($lastError['message']); 71 | } 72 | 73 | return $response; 74 | } 75 | 76 | private function generateStreamContext($body, $headers, $method) 77 | { 78 | return stream_context_create( 79 | [ 80 | 'http' => [ 81 | 'method' => $method, 82 | 'header' => implode("\r\n", array_values($headers)), 83 | 'content' => $body, 84 | 'protocol_version' => '1.1', 85 | 'user_agent' => $this->userAgent, 86 | 'max_redirects' => $this->maxRedirects, 87 | 'timeout' => $this->timeout, 88 | ], 89 | ] 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/OAuth/Common/Http/Exception/TokenResponseException.php: -------------------------------------------------------------------------------- 1 | credentials = $credentials; 32 | $this->httpClient = $httpClient; 33 | $this->storage = $storage; 34 | } 35 | 36 | /** 37 | * @param string|UriInterface $path 38 | * @param UriInterface $baseApiUri 39 | * 40 | * @return UriInterface 41 | */ 42 | protected function determineRequestUriFromPath($path, ?UriInterface $baseApiUri = null) 43 | { 44 | if ($path instanceof UriInterface) { 45 | $uri = $path; 46 | } elseif (stripos($path, 'http://') === 0 || stripos($path, 'https://') === 0) { 47 | $uri = new Uri($path); 48 | } else { 49 | if (null === $baseApiUri) { 50 | throw new Exception( 51 | 'An absolute URI must be passed to ServiceInterface::request as no baseApiUri is set.' 52 | ); 53 | } 54 | 55 | $uri = clone $baseApiUri; 56 | if (false !== strpos($path, '?')) { 57 | $parts = explode('?', $path, 2); 58 | $path = $parts[0]; 59 | $query = $parts[1]; 60 | $uri->setQuery($query); 61 | } 62 | 63 | if ($path[0] === '/') { 64 | $path = substr($path, 1); 65 | } 66 | 67 | $uri->setPath($uri->getPath() . $path); 68 | } 69 | 70 | return $uri; 71 | } 72 | 73 | /** 74 | * Accessor to the storage adapter to be able to retrieve tokens. 75 | * 76 | * @return TokenStorageInterface 77 | */ 78 | public function getStorage() 79 | { 80 | return $this->storage; 81 | } 82 | 83 | /** 84 | * @return string 85 | */ 86 | public function service() 87 | { 88 | // get class name without backslashes 89 | $classname = get_class($this); 90 | 91 | return preg_replace('/^.*\\\\/', '', $classname); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/OAuth/Common/Service/ServiceInterface.php: -------------------------------------------------------------------------------- 1 | tokens = []; 25 | $this->states = []; 26 | } 27 | 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | public function retrieveAccessToken($service) 32 | { 33 | if ($this->hasAccessToken($service)) { 34 | return $this->tokens[$service]; 35 | } 36 | 37 | throw new TokenNotFoundException('Token not stored'); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function storeAccessToken($service, TokenInterface $token) 44 | { 45 | $this->tokens[$service] = $token; 46 | 47 | // allow chaining 48 | return $this; 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function hasAccessToken($service) 55 | { 56 | return isset($this->tokens[$service]) && $this->tokens[$service] instanceof TokenInterface; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function clearToken($service) 63 | { 64 | if (array_key_exists($service, $this->tokens)) { 65 | unset($this->tokens[$service]); 66 | } 67 | 68 | // allow chaining 69 | return $this; 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function clearAllTokens() 76 | { 77 | $this->tokens = []; 78 | 79 | // allow chaining 80 | return $this; 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | public function retrieveAuthorizationState($service) 87 | { 88 | if ($this->hasAuthorizationState($service)) { 89 | return $this->states[$service]; 90 | } 91 | 92 | throw new AuthorizationStateNotFoundException('State not stored'); 93 | } 94 | 95 | /** 96 | * {@inheritdoc} 97 | */ 98 | public function storeAuthorizationState($service, $state) 99 | { 100 | $this->states[$service] = $state; 101 | 102 | // allow chaining 103 | return $this; 104 | } 105 | 106 | /** 107 | * {@inheritdoc} 108 | */ 109 | public function hasAuthorizationState($service) 110 | { 111 | return isset($this->states[$service]) && null !== $this->states[$service]; 112 | } 113 | 114 | /** 115 | * {@inheritdoc} 116 | */ 117 | public function clearAuthorizationState($service) 118 | { 119 | if (array_key_exists($service, $this->states)) { 120 | unset($this->states[$service]); 121 | } 122 | 123 | // allow chaining 124 | return $this; 125 | } 126 | 127 | /** 128 | * {@inheritdoc} 129 | */ 130 | public function clearAllAuthorizationStates() 131 | { 132 | $this->states = []; 133 | 134 | // allow chaining 135 | return $this; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/OAuth/Common/Storage/TokenStorageInterface.php: -------------------------------------------------------------------------------- 1 | accessToken = $accessToken; 39 | $this->refreshToken = $refreshToken; 40 | $this->setLifetime($lifetime); 41 | $this->extraParams = $extraParams; 42 | } 43 | 44 | /** 45 | * @return string 46 | */ 47 | public function getAccessToken() 48 | { 49 | return $this->accessToken; 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getRefreshToken() 56 | { 57 | return $this->refreshToken; 58 | } 59 | 60 | /** 61 | * @return int 62 | */ 63 | public function getEndOfLife() 64 | { 65 | return $this->endOfLife; 66 | } 67 | 68 | public function setExtraParams(array $extraParams): void 69 | { 70 | $this->extraParams = $extraParams; 71 | } 72 | 73 | /** 74 | * @return array 75 | */ 76 | public function getExtraParams() 77 | { 78 | return $this->extraParams; 79 | } 80 | 81 | /** 82 | * @param string $accessToken 83 | */ 84 | public function setAccessToken($accessToken): void 85 | { 86 | $this->accessToken = $accessToken; 87 | } 88 | 89 | /** 90 | * @param int $endOfLife 91 | */ 92 | public function setEndOfLife($endOfLife): void 93 | { 94 | $this->endOfLife = $endOfLife; 95 | } 96 | 97 | /** 98 | * @param int $lifetime 99 | */ 100 | public function setLifetime($lifetime): void 101 | { 102 | if (0 === $lifetime || static::EOL_NEVER_EXPIRES === $lifetime) { 103 | $this->endOfLife = static::EOL_NEVER_EXPIRES; 104 | } elseif (null !== $lifetime) { 105 | $this->endOfLife = (int) $lifetime + time(); 106 | } else { 107 | $this->endOfLife = static::EOL_UNKNOWN; 108 | } 109 | } 110 | 111 | /** 112 | * @param string $refreshToken 113 | */ 114 | public function setRefreshToken($refreshToken): void 115 | { 116 | $this->refreshToken = $refreshToken; 117 | } 118 | 119 | public function isExpired() 120 | { 121 | return $this->getEndOfLife() !== TokenInterface::EOL_NEVER_EXPIRES 122 | && $this->getEndOfLife() !== TokenInterface::EOL_UNKNOWN 123 | && time() > $this->getEndOfLife(); 124 | } 125 | 126 | public function __sleep() 127 | { 128 | return ['accessToken']; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/OAuth/Common/Token/Exception/ExpiredTokenException.php: -------------------------------------------------------------------------------- 1 | finder = new Finder(); 22 | } 23 | 24 | public function isCli(): bool 25 | { 26 | return PHP_SAPI === 'cli'; 27 | } 28 | 29 | public function getFinder(): Finder 30 | { 31 | $this->finder->in(__DIR__ . '/../../../examples/provider/'); 32 | 33 | return $this->finder; 34 | } 35 | 36 | public function getHeader(): string 37 | { 38 | $title = $this->title; 39 | 40 | return << 42 | 43 | $title 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | 74 |

$title

75 | HTML; 76 | } 77 | 78 | public function getFooter() 79 | { 80 | return << 82 | 83 | HTML; 84 | } 85 | 86 | public function getForm(): string 87 | { 88 | return << 90 |
91 | 92 | 93 |
94 |
95 | 96 | 97 |
98 | 99 | 100 | HTML; 101 | } 102 | 103 | public function getContent(): string 104 | { 105 | $response = $this->getHeader(); 106 | $response .= $this->getForm(); 107 | $response .= $this->getFooter(); 108 | 109 | return $response; 110 | } 111 | 112 | public function isShowLink(): bool 113 | { 114 | return true; 115 | } 116 | 117 | public function getCurrentUrl(): string 118 | { 119 | return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?oauth=redirect&key=' . urldecode($_GET['key']) . '&secret=' . urldecode($_GET['secret']); 120 | } 121 | 122 | public function getErrorMessage($exception): void 123 | { 124 | echo '
' . $exception->getMessage() . '
'; 125 | echo '
';
126 |         print_r($exception);
127 |         echo '
'; 128 | } 129 | 130 | public function setTitle(string $title): void 131 | { 132 | $this->title = 'PHPoAuthLib - ' . $title; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/BitBucket.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://bitbucket.org/api/1.0/'); 27 | } 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function getRequestTokenEndpoint() 34 | { 35 | return new Uri('https://bitbucket.org/!api/1.0/oauth/request_token'); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getAuthorizationEndpoint() 42 | { 43 | return new Uri('https://bitbucket.org/!api/1.0/oauth/authenticate'); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getAccessTokenEndpoint() 50 | { 51 | return new Uri('https://bitbucket.org/!api/1.0/oauth/access_token'); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function parseRequestTokenResponse($responseBody) 58 | { 59 | parse_str($responseBody, $data); 60 | 61 | if (null === $data || !is_array($data)) { 62 | throw new TokenResponseException('Unable to parse response.'); 63 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 64 | throw new TokenResponseException('Error in retrieving token.'); 65 | } 66 | 67 | return $this->parseAccessTokenResponse($responseBody); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function parseAccessTokenResponse($responseBody) 74 | { 75 | parse_str($responseBody, $data); 76 | 77 | if (null === $data || !is_array($data)) { 78 | throw new TokenResponseException('Unable to parse response.'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth1Token(); 84 | 85 | $token->setRequestToken($data['oauth_token']); 86 | $token->setRequestTokenSecret($data['oauth_token_secret']); 87 | $token->setAccessToken($data['oauth_token']); 88 | $token->setAccessTokenSecret($data['oauth_token_secret']); 89 | 90 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 91 | unset($data['oauth_token'], $data['oauth_token_secret']); 92 | $token->setExtraParams($data); 93 | 94 | return $token; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/Etsy.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://openapi.etsy.com/v2/'); 29 | } 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function getRequestTokenEndpoint() 36 | { 37 | $uri = new Uri($this->baseApiUri . 'oauth/request_token'); 38 | $scopes = $this->getScopes(); 39 | 40 | if (count($scopes)) { 41 | $uri->setQuery('scope=' . implode('%20', $scopes)); 42 | } 43 | 44 | return $uri; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function getAuthorizationEndpoint() 51 | { 52 | return new Uri($this->baseApiUri); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function getAccessTokenEndpoint() 59 | { 60 | return new Uri($this->baseApiUri . 'oauth/access_token'); 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | */ 66 | protected function parseRequestTokenResponse($responseBody) 67 | { 68 | parse_str($responseBody, $data); 69 | 70 | if (null === $data || !is_array($data)) { 71 | throw new TokenResponseException('Unable to parse response.'); 72 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 73 | throw new TokenResponseException('Error in retrieving token.'); 74 | } 75 | 76 | return $this->parseAccessTokenResponse($responseBody); 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | protected function parseAccessTokenResponse($responseBody) 83 | { 84 | parse_str($responseBody, $data); 85 | 86 | if (null === $data || !is_array($data)) { 87 | throw new TokenResponseException('Unable to parse response.'); 88 | } elseif (isset($data['error'])) { 89 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 90 | } 91 | 92 | $token = new StdOAuth1Token(); 93 | 94 | $token->setRequestToken($data['oauth_token']); 95 | $token->setRequestTokenSecret($data['oauth_token_secret']); 96 | $token->setAccessToken($data['oauth_token']); 97 | $token->setAccessTokenSecret($data['oauth_token_secret']); 98 | 99 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 100 | unset($data['oauth_token'], $data['oauth_token_secret']); 101 | $token->setExtraParams($data); 102 | 103 | return $token; 104 | } 105 | 106 | /** 107 | * Set the scopes for permissions. 108 | * 109 | * @see https://www.etsy.com/developers/documentation/getting_started/oauth#section_permission_scopes 110 | * 111 | * @return $this 112 | */ 113 | public function setScopes(array $scopes) 114 | { 115 | if (!is_array($scopes)) { 116 | $scopes = []; 117 | } 118 | 119 | $this->scopes = $scopes; 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * Return the defined scopes. 126 | * 127 | * @return array 128 | */ 129 | public function getScopes() 130 | { 131 | return $this->scopes; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/FitBit.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.fitbit.com/1/'); 27 | } 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function getRequestTokenEndpoint() 34 | { 35 | return new Uri('https://api.fitbit.com/oauth/request_token'); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getAuthorizationEndpoint() 42 | { 43 | return new Uri('https://www.fitbit.com/oauth/authorize'); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getAccessTokenEndpoint() 50 | { 51 | return new Uri('https://api.fitbit.com/oauth/access_token'); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function parseRequestTokenResponse($responseBody) 58 | { 59 | parse_str($responseBody, $data); 60 | 61 | if (null === $data || !is_array($data)) { 62 | throw new TokenResponseException('Unable to parse response.'); 63 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 64 | throw new TokenResponseException('Error in retrieving token.'); 65 | } 66 | 67 | return $this->parseAccessTokenResponse($responseBody); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function parseAccessTokenResponse($responseBody) 74 | { 75 | parse_str($responseBody, $data); 76 | 77 | if (null === $data || !is_array($data)) { 78 | throw new TokenResponseException('Unable to parse response.'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth1Token(); 84 | 85 | $token->setRequestToken($data['oauth_token']); 86 | $token->setRequestTokenSecret($data['oauth_token_secret']); 87 | $token->setAccessToken($data['oauth_token']); 88 | $token->setAccessTokenSecret($data['oauth_token_secret']); 89 | 90 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 91 | unset($data['oauth_token'], $data['oauth_token_secret']); 92 | $token->setExtraParams($data); 93 | 94 | return $token; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/FiveHundredPx.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://developers.500px.com/ 9 | */ 10 | 11 | namespace OAuth\OAuth1\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth1\Signature\SignatureInterface; 20 | use OAuth\OAuth1\Token\StdOAuth1Token; 21 | 22 | /** 23 | * 500px service. 24 | * 25 | * @author Pedro Amorim 26 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 27 | * 28 | * @see https://developers.500px.com/ 29 | */ 30 | class FiveHundredPx extends AbstractService 31 | { 32 | public function __construct( 33 | CredentialsInterface $credentials, 34 | ClientInterface $httpClient, 35 | TokenStorageInterface $storage, 36 | SignatureInterface $signature, 37 | ?UriInterface $baseApiUri = null 38 | ) { 39 | parent::__construct( 40 | $credentials, 41 | $httpClient, 42 | $storage, 43 | $signature, 44 | $baseApiUri 45 | ); 46 | 47 | if (null === $baseApiUri) { 48 | $this->baseApiUri = new Uri('https://api.500px.com/v1/'); 49 | } 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getRequestTokenEndpoint() 56 | { 57 | return new Uri('https://api.500px.com/v1/oauth/request_token'); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getAuthorizationEndpoint() 64 | { 65 | return new Uri('https://api.500px.com/v1/oauth/authorize'); 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | public function getAccessTokenEndpoint() 72 | { 73 | return new Uri('https://api.500px.com/v1/oauth/access_token'); 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | protected function parseRequestTokenResponse($responseBody) 80 | { 81 | parse_str($responseBody, $data); 82 | 83 | if (null === $data || !is_array($data)) { 84 | throw new TokenResponseException('Unable to parse response.'); 85 | } elseif (!isset($data['oauth_callback_confirmed']) 86 | || $data['oauth_callback_confirmed'] !== 'true' 87 | ) { 88 | throw new TokenResponseException('Error in retrieving token.'); 89 | } 90 | 91 | return $this->parseAccessTokenResponse($responseBody); 92 | } 93 | 94 | /** 95 | * {@inheritdoc} 96 | */ 97 | protected function parseAccessTokenResponse($responseBody) 98 | { 99 | parse_str($responseBody, $data); 100 | 101 | if (null === $data || !is_array($data)) { 102 | throw new TokenResponseException('Unable to parse response.'); 103 | } elseif (isset($data['error'])) { 104 | throw new TokenResponseException( 105 | 'Error in retrieving token: "' . $data['error'] . '"' 106 | ); 107 | } 108 | 109 | $token = new StdOAuth1Token(); 110 | 111 | $token->setRequestToken($data['oauth_token']); 112 | $token->setRequestTokenSecret($data['oauth_token_secret']); 113 | $token->setAccessToken($data['oauth_token']); 114 | $token->setAccessTokenSecret($data['oauth_token_secret']); 115 | 116 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 117 | unset($data['oauth_token'], $data['oauth_token_secret']); 118 | $token->setExtraParams($data); 119 | 120 | return $token; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/QuickBooks.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://quickbooks.api.intuit.com/'); 36 | } 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getRequestTokenEndpoint() 43 | { 44 | return new Uri('https://oauth.intuit.com/oauth/v1/get_request_token'); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function getAuthorizationEndpoint() 51 | { 52 | return new Uri('https://appcenter.intuit.com/Connect/Begin'); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function getAccessTokenEndpoint() 59 | { 60 | return new Uri('https://oauth.intuit.com/oauth/v1/get_access_token'); 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | */ 66 | protected function parseRequestTokenResponse($responseBody) 67 | { 68 | parse_str($responseBody, $data); 69 | 70 | if (null === $data || !is_array($data)) { 71 | throw new TokenResponseException('Unable to parse response.'); 72 | } elseif (!isset($data['oauth_callback_confirmed']) 73 | || $data['oauth_callback_confirmed'] !== 'true') { 74 | throw new TokenResponseException('Error in retrieving token.'); 75 | } 76 | 77 | return $this->parseAccessTokenResponse($responseBody); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function parseAccessTokenResponse($responseBody) 84 | { 85 | parse_str($responseBody, $data); 86 | 87 | if (null === $data || !is_array($data)) { 88 | throw new TokenResponseException('Unable to parse response.'); 89 | } elseif (isset($data['error'])) { 90 | $message = 'Error in retrieving token: "' . $data['error'] . '"'; 91 | 92 | throw new TokenResponseException($message); 93 | } 94 | 95 | $token = new StdOAuth1Token(); 96 | 97 | $token->setRequestToken($data['oauth_token']); 98 | $token->setRequestTokenSecret($data['oauth_token_secret']); 99 | $token->setAccessToken($data['oauth_token']); 100 | $token->setAccessTokenSecret($data['oauth_token_secret']); 101 | 102 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 103 | unset($data['oauth_token'], $data['oauth_token_secret']); 104 | $token->setExtraParams($data); 105 | 106 | return $token; 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | public function request( 113 | $path, 114 | $method = 'GET', 115 | $body = null, 116 | array $extraHeaders = [] 117 | ) { 118 | $extraHeaders['Accept'] = 'application/json'; 119 | 120 | return parent::request($path, $method, $body, $extraHeaders); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/Redmine.php: -------------------------------------------------------------------------------- 1 | baseApiUri->getAbsoluteUri() . '/request_token'); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getAuthorizationEndpoint() 43 | { 44 | return new Uri($this->baseApiUri->getAbsoluteUri() . '/authorize'); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function getAccessTokenEndpoint() 51 | { 52 | return new Uri($this->baseApiUri->getAbsoluteUri() . '/access_token'); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | protected function parseRequestTokenResponse($responseBody) 59 | { 60 | parse_str($responseBody, $data); 61 | 62 | if (null === $data || !is_array($data)) { 63 | throw new TokenResponseException('Unable to parse response.'); 64 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 65 | throw new TokenResponseException('Error in retrieving token.'); 66 | } 67 | 68 | return $this->parseAccessTokenResponse($responseBody); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | protected function parseAccessTokenResponse($responseBody) 75 | { 76 | parse_str($responseBody, $data); 77 | 78 | if (null === $data || !is_array($data)) { 79 | throw new TokenResponseException('Unable to parse response.'); 80 | } elseif (isset($data['error'])) { 81 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 82 | } 83 | 84 | $token = new StdOAuth1Token(); 85 | 86 | $token->setRequestToken($data['oauth_token']); 87 | $token->setRequestTokenSecret($data['oauth_token_secret']); 88 | $token->setAccessToken($data['oauth_token']); 89 | $token->setAccessTokenSecret($data['oauth_token_secret']); 90 | 91 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 92 | unset($data['oauth_token'], $data['oauth_token_secret']); 93 | $token->setExtraParams($data); 94 | 95 | return $token; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/ScoopIt.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://www.scoop.it/api/1/'); 27 | } 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function getRequestTokenEndpoint() 34 | { 35 | return new Uri('https://www.scoop.it/oauth/request'); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getAuthorizationEndpoint() 42 | { 43 | return new Uri('https://www.scoop.it/oauth/authorize'); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getAccessTokenEndpoint() 50 | { 51 | return new Uri('https://www.scoop.it/oauth/access'); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function parseRequestTokenResponse($responseBody) 58 | { 59 | parse_str($responseBody, $data); 60 | 61 | if (null === $data || !is_array($data)) { 62 | throw new TokenResponseException('Unable to parse response.'); 63 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 64 | throw new TokenResponseException('Error in retrieving token.'); 65 | } 66 | 67 | return $this->parseAccessTokenResponse($responseBody); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function parseAccessTokenResponse($responseBody) 74 | { 75 | parse_str($responseBody, $data); 76 | 77 | if (null === $data || !is_array($data)) { 78 | throw new TokenResponseException('Unable to parse response.'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth1Token(); 84 | 85 | $token->setRequestToken($data['oauth_token']); 86 | $token->setRequestTokenSecret($data['oauth_token_secret']); 87 | $token->setAccessToken($data['oauth_token']); 88 | $token->setAccessTokenSecret($data['oauth_token_secret']); 89 | 90 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 91 | unset($data['oauth_token'], $data['oauth_token_secret']); 92 | $token->setExtraParams($data); 93 | 94 | return $token; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/ServiceInterface.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.tumblr.com/v2/'); 27 | } 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function getRequestTokenEndpoint() 34 | { 35 | return new Uri('https://www.tumblr.com/oauth/request_token'); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getAuthorizationEndpoint() 42 | { 43 | return new Uri('https://www.tumblr.com/oauth/authorize'); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getAccessTokenEndpoint() 50 | { 51 | return new Uri('https://www.tumblr.com/oauth/access_token'); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function parseRequestTokenResponse($responseBody) 58 | { 59 | parse_str($responseBody, $data); 60 | 61 | if (null === $data || !is_array($data)) { 62 | throw new TokenResponseException('Unable to parse response.'); 63 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 64 | throw new TokenResponseException('Error in retrieving token.'); 65 | } 66 | 67 | return $this->parseAccessTokenResponse($responseBody); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function parseAccessTokenResponse($responseBody) 74 | { 75 | parse_str($responseBody, $data); 76 | 77 | if (null === $data || !is_array($data)) { 78 | throw new TokenResponseException('Unable to parse response.'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth1Token(); 84 | 85 | $token->setRequestToken($data['oauth_token']); 86 | $token->setRequestTokenSecret($data['oauth_token_secret']); 87 | $token->setAccessToken($data['oauth_token']); 88 | $token->setAccessTokenSecret($data['oauth_token_secret']); 89 | 90 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 91 | unset($data['oauth_token'], $data['oauth_token_secret']); 92 | $token->setExtraParams($data); 93 | 94 | return $token; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/Twitter.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.twitter.com/1.1/'); 33 | } 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getRequestTokenEndpoint() 40 | { 41 | return new Uri('https://api.twitter.com/oauth/request_token'); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getAuthorizationEndpoint() 48 | { 49 | if ($this->authorizationEndpoint != self::ENDPOINT_AUTHENTICATE 50 | && $this->authorizationEndpoint != self::ENDPOINT_AUTHORIZE) { 51 | $this->authorizationEndpoint = self::ENDPOINT_AUTHENTICATE; 52 | } 53 | 54 | return new Uri($this->authorizationEndpoint); 55 | } 56 | 57 | /** 58 | * @param mixed $endpoint 59 | */ 60 | public function setAuthorizationEndpoint($endpoint): void 61 | { 62 | if ($endpoint != self::ENDPOINT_AUTHENTICATE && $endpoint != self::ENDPOINT_AUTHORIZE) { 63 | throw new Exception( 64 | sprintf("'%s' is not a correct Twitter authorization endpoint.", $endpoint) 65 | ); 66 | } 67 | $this->authorizationEndpoint = $endpoint; 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | public function getAccessTokenEndpoint() 74 | { 75 | return new Uri('https://api.twitter.com/oauth/access_token'); 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | */ 81 | protected function parseRequestTokenResponse($responseBody) 82 | { 83 | parse_str($responseBody, $data); 84 | 85 | if (null === $data || !is_array($data)) { 86 | throw new TokenResponseException('Unable to parse response.'); 87 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 88 | throw new TokenResponseException('Error in retrieving token.'); 89 | } 90 | 91 | return $this->parseAccessTokenResponse($responseBody); 92 | } 93 | 94 | /** 95 | * {@inheritdoc} 96 | */ 97 | protected function parseAccessTokenResponse($responseBody) 98 | { 99 | parse_str($responseBody, $data); 100 | 101 | if (null === $data || !is_array($data)) { 102 | throw new TokenResponseException('Unable to parse response: ' . $responseBody); 103 | } elseif (isset($data['error'])) { 104 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 105 | } elseif (!isset($data['oauth_token']) || !isset($data['oauth_token_secret'])) { 106 | throw new TokenResponseException('Invalid response. OAuth Token data not set: ' . $responseBody); 107 | } 108 | 109 | $token = new StdOAuth1Token(); 110 | 111 | $token->setRequestToken($data['oauth_token']); 112 | $token->setRequestTokenSecret($data['oauth_token_secret']); 113 | $token->setAccessToken($data['oauth_token']); 114 | $token->setAccessTokenSecret($data['oauth_token_secret']); 115 | 116 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 117 | unset($data['oauth_token'], $data['oauth_token_secret']); 118 | $token->setExtraParams($data); 119 | 120 | return $token; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Service/Yahoo.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://social.yahooapis.com/v1/'); 28 | } 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function getRequestTokenEndpoint() 35 | { 36 | return new Uri('https://api.login.yahoo.com/oauth/v2/get_request_token'); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getAuthorizationEndpoint() 43 | { 44 | return new Uri('https://api.login.yahoo.com/oauth/v2/request_auth'); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function getAccessTokenEndpoint() 51 | { 52 | return new Uri('https://api.login.yahoo.com/oauth/v2/get_token'); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function refreshAccessToken(TokenInterface $token) 59 | { 60 | $extraParams = $token->getExtraParams(); 61 | $bodyParams = ['oauth_session_handle' => $extraParams['oauth_session_handle']]; 62 | 63 | $authorizationHeader = [ 64 | 'Authorization' => $this->buildAuthorizationHeaderForAPIRequest( 65 | 'POST', 66 | $this->getAccessTokenEndpoint(), 67 | $this->storage->retrieveAccessToken($this->service()), 68 | $bodyParams 69 | ), 70 | ]; 71 | 72 | $headers = array_merge($authorizationHeader, $this->getExtraOAuthHeaders(), []); 73 | 74 | $responseBody = $this->httpClient->retrieveResponse($this->getAccessTokenEndpoint(), $bodyParams, $headers); 75 | 76 | $token = $this->parseAccessTokenResponse($responseBody); 77 | $this->storage->storeAccessToken($this->service(), $token); 78 | 79 | return $token; 80 | } 81 | 82 | /** 83 | * {@inheritdoc} 84 | */ 85 | protected function parseRequestTokenResponse($responseBody) 86 | { 87 | parse_str($responseBody, $data); 88 | 89 | if (null === $data || !is_array($data)) { 90 | throw new TokenResponseException('Unable to parse response.'); 91 | } elseif (!isset($data['oauth_callback_confirmed']) || $data['oauth_callback_confirmed'] !== 'true') { 92 | throw new TokenResponseException('Error in retrieving token.'); 93 | } 94 | 95 | return $this->parseAccessTokenResponse($responseBody); 96 | } 97 | 98 | /** 99 | * {@inheritdoc} 100 | */ 101 | protected function parseAccessTokenResponse($responseBody) 102 | { 103 | parse_str($responseBody, $data); 104 | 105 | if (null === $data || !is_array($data)) { 106 | throw new TokenResponseException('Unable to parse response.'); 107 | } elseif (isset($data['error'])) { 108 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 109 | } 110 | 111 | $token = new StdOAuth1Token(); 112 | 113 | $token->setRequestToken($data['oauth_token']); 114 | $token->setRequestTokenSecret($data['oauth_token_secret']); 115 | $token->setAccessToken($data['oauth_token']); 116 | $token->setAccessTokenSecret($data['oauth_token_secret']); 117 | 118 | if (isset($data['oauth_expires_in'])) { 119 | $token->setLifetime($data['oauth_expires_in']); 120 | } else { 121 | $token->setEndOfLife(StdOAuth1Token::EOL_NEVER_EXPIRES); 122 | } 123 | 124 | unset($data['oauth_token'], $data['oauth_token_secret']); 125 | $token->setExtraParams($data); 126 | 127 | return $token; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Signature/Exception/UnsupportedHashAlgorithmException.php: -------------------------------------------------------------------------------- 1 | credentials = $credentials; 29 | } 30 | 31 | /** 32 | * @param string $algorithm 33 | */ 34 | public function setHashingAlgorithm($algorithm): void 35 | { 36 | $this->algorithm = $algorithm; 37 | } 38 | 39 | /** 40 | * @param string $token 41 | */ 42 | public function setTokenSecret($token): void 43 | { 44 | $this->tokenSecret = $token; 45 | } 46 | 47 | /** 48 | * @param string $method 49 | * 50 | * @return string 51 | */ 52 | public function getSignature(UriInterface $uri, array $params, $method = 'POST') 53 | { 54 | parse_str($uri->getQuery(), $queryStringData); 55 | 56 | foreach (array_merge($queryStringData, $params) as $key => $value) { 57 | $signatureData[rawurlencode($key)] = rawurlencode($value); 58 | } 59 | 60 | ksort($signatureData); 61 | 62 | // determine base uri 63 | $baseUri = $uri->getScheme() . '://' . $uri->getRawAuthority(); 64 | 65 | if ('/' === $uri->getPath()) { 66 | $baseUri .= $uri->hasExplicitTrailingHostSlash() ? '/' : ''; 67 | } else { 68 | $baseUri .= $uri->getPath(); 69 | } 70 | 71 | $baseString = strtoupper($method) . '&'; 72 | $baseString .= rawurlencode($baseUri) . '&'; 73 | $baseString .= rawurlencode($this->buildSignatureDataString($signatureData)); 74 | 75 | return base64_encode($this->hash($baseString)); 76 | } 77 | 78 | /** 79 | * @return string 80 | */ 81 | protected function buildSignatureDataString(array $signatureData) 82 | { 83 | $signatureString = ''; 84 | $delimiter = ''; 85 | foreach ($signatureData as $key => $value) { 86 | $signatureString .= $delimiter . $key . '=' . $value; 87 | 88 | $delimiter = '&'; 89 | } 90 | 91 | return $signatureString; 92 | } 93 | 94 | /** 95 | * @return string 96 | */ 97 | protected function getSigningKey() 98 | { 99 | $signingKey = rawurlencode($this->credentials->getConsumerSecret()) . '&'; 100 | if ($this->tokenSecret !== null) { 101 | $signingKey .= rawurlencode($this->tokenSecret); 102 | } 103 | 104 | return $signingKey; 105 | } 106 | 107 | /** 108 | * @param string $data 109 | * 110 | * @return string 111 | */ 112 | protected function hash($data) 113 | { 114 | switch (strtoupper($this->algorithm)) { 115 | case 'HMAC-SHA1': 116 | return hash_hmac('sha1', $data, $this->getSigningKey(), true); 117 | default: 118 | throw new UnsupportedHashAlgorithmException( 119 | 'Unsupported hashing algorithm (' . $this->algorithm . ') used.' 120 | ); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Signature/SignatureInterface.php: -------------------------------------------------------------------------------- 1 | requestToken = $requestToken; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getRequestToken() 40 | { 41 | return $this->requestToken; 42 | } 43 | 44 | /** 45 | * @param string $requestTokenSecret 46 | */ 47 | public function setRequestTokenSecret($requestTokenSecret): void 48 | { 49 | $this->requestTokenSecret = $requestTokenSecret; 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getRequestTokenSecret() 56 | { 57 | return $this->requestTokenSecret; 58 | } 59 | 60 | /** 61 | * @param string $accessTokenSecret 62 | */ 63 | public function setAccessTokenSecret($accessTokenSecret): void 64 | { 65 | $this->accessTokenSecret = $accessTokenSecret; 66 | } 67 | 68 | /** 69 | * @return string 70 | */ 71 | public function getAccessTokenSecret() 72 | { 73 | return $this->accessTokenSecret; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/OAuth/OAuth1/Token/TokenInterface.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see https://images-na.ssl-images-amazon.com/images/G/01/lwa/dev/docs/website-developer-guide._TTH_.pdf 19 | */ 20 | class Amazon extends AbstractService 21 | { 22 | /** 23 | * Defined scopes. 24 | * 25 | * @see https://images-na.ssl-images-amazon.com/images/G/01/lwa/dev/docs/website-developer-guide._TTH_.pdf 26 | */ 27 | const SCOPE_PROFILE = 'profile'; 28 | const SCOPE_POSTAL_CODE = 'postal_code'; 29 | 30 | public function __construct( 31 | CredentialsInterface $credentials, 32 | ClientInterface $httpClient, 33 | TokenStorageInterface $storage, 34 | $scopes = [], 35 | ?UriInterface $baseApiUri = null 36 | ) { 37 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 38 | 39 | if (null === $baseApiUri) { 40 | $this->baseApiUri = new Uri('https://api.amazon.com/'); 41 | } 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getAuthorizationEndpoint() 48 | { 49 | return new Uri('https://www.amazon.com/ap/oa'); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getAccessTokenEndpoint() 56 | { 57 | return new Uri('https://www.amazon.com/ap/oatoken'); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | protected function getAuthorizationMethod() 64 | { 65 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | protected function parseAccessTokenResponse($responseBody) 72 | { 73 | $data = json_decode($responseBody, true); 74 | 75 | if (null === $data || !is_array($data)) { 76 | throw new TokenResponseException('Unable to parse response.'); 77 | } elseif (isset($data['error_description'])) { 78 | throw new TokenResponseException('Error in retrieving token: "' . $data['error_description'] . '"'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth2Token(); 84 | $token->setAccessToken($data['access_token']); 85 | $token->setLifeTime($data['expires_in']); 86 | 87 | if (isset($data['refresh_token'])) { 88 | $token->setRefreshToken($data['refresh_token']); 89 | unset($data['refresh_token']); 90 | } 91 | 92 | unset($data['access_token'], $data['expires_in']); 93 | 94 | $token->setExtraParams($data); 95 | 96 | return $token; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/BattleNet.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri(self::API_URI_US); 48 | } 49 | } 50 | 51 | /** ----------------------------------------------------------------------- 52 | * Translates the current base API URI into an OAuth base URI. 53 | * 54 | * @returns string Base URI of oauth services. 55 | */ 56 | private function GetOAuthBaseUri() 57 | { 58 | 59 | // i love china 60 | switch ($this->baseApiUri) { 61 | case self::API_URI_US: return 'https://us.battle.net/oauth/'; 62 | case self::API_URI_EU: return 'https://eu.battle.net/oauth/'; 63 | case self::API_URI_KR: return 'https://kr.battle.net/oauth/'; 64 | case self::API_URI_TW: return 'https://tw.battle.net/oauth/'; 65 | case self::API_URI_CN: return 'https://www.battlenet.com.cn/oauth/'; 66 | case self::API_URI_SEA: return 'https://sea.battle.net/oauth/'; 67 | } 68 | } 69 | 70 | /** ----------------------------------------------------------------------- 71 | * {@inheritdoc} 72 | */ 73 | public function getAuthorizationEndpoint() 74 | { 75 | return new Uri($this->GetOAuthBaseUri() . 'authorize'); 76 | } 77 | 78 | /** ----------------------------------------------------------------------- 79 | * {@inheritdoc} 80 | */ 81 | public function getAccessTokenEndpoint() 82 | { 83 | return new Uri($this->GetOAuthBaseUri() . 'token'); 84 | } 85 | 86 | /** ----------------------------------------------------------------------- 87 | * {@inheritdoc} 88 | */ 89 | protected function getAuthorizationMethod() 90 | { 91 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 92 | } 93 | 94 | /** ----------------------------------------------------------------------- 95 | * {@inheritdoc} 96 | */ 97 | protected function parseAccessTokenResponse($responseBody) 98 | { 99 | $data = json_decode($responseBody, true); 100 | if ($data === null || !is_array($data)) { 101 | throw new TokenResponseException('Unable to parse response.'); 102 | } elseif (isset($data['error'])) { 103 | $err = $data['error']; 104 | 105 | throw new TokenResponseException( 106 | "Error in retrieving token: \"$err\""); 107 | } 108 | 109 | $token = new StdOAuth2Token($data['access_token'], null, 110 | $data['expires_in']); 111 | 112 | unset($data['access_token'] , $data['expires_in']); 113 | 114 | $token->setExtraParams($data); 115 | 116 | return $token; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Bitly.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api-ssl.bitly.com/v3/'); 26 | } 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function getAuthorizationEndpoint() 33 | { 34 | return new Uri('https://bitly.com/oauth/authorize'); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAccessTokenEndpoint() 41 | { 42 | return new Uri('https://api-ssl.bitly.com/oauth/access_token'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | protected function getAuthorizationMethod() 49 | { 50 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function parseAccessTokenResponse($responseBody) 57 | { 58 | $data = json_decode($responseBody, true); 59 | 60 | if (null === $data || !is_array($data)) { 61 | throw new TokenResponseException('Unable to parse response.'); 62 | } elseif (isset($data['error'])) { 63 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 64 | } 65 | 66 | $token = new StdOAuth2Token(); 67 | $token->setAccessToken($data['access_token']); 68 | // I'm invincible!!! 69 | $token->setEndOfLife(StdOAuth2Token::EOL_NEVER_EXPIRES); 70 | unset($data['access_token']); 71 | 72 | $token->setExtraParams($data); 73 | 74 | return $token; 75 | } 76 | 77 | /** 78 | * {@inheritdoc} 79 | */ 80 | public function requestAccessToken($code, $state = null) 81 | { 82 | if (null !== $state) { 83 | $this->validateAuthorizationState($state); 84 | } 85 | 86 | $bodyParams = [ 87 | 'code' => $code, 88 | 'client_id' => $this->credentials->getConsumerId(), 89 | 'client_secret' => $this->credentials->getConsumerSecret(), 90 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 91 | 'grant_type' => 'authorization_code', 92 | ]; 93 | 94 | $responseBody = $this->httpClient->retrieveResponse( 95 | $this->getAccessTokenEndpoint(), 96 | $bodyParams, 97 | $this->getExtraOAuthHeaders() 98 | ); 99 | 100 | // we can scream what we want that we want bitly to return a json encoded string (format=json), but the 101 | // WOAH WATCH YOUR LANGUAGE ;) service doesn't seem to like screaming, hence we need to manually 102 | // parse the result 103 | $parsedResult = []; 104 | parse_str($responseBody, $parsedResult); 105 | 106 | $token = $this->parseAccessTokenResponse(json_encode($parsedResult)); 107 | $this->storage->storeAccessToken($this->service(), $token); 108 | 109 | return $token; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Bitrix24.php: -------------------------------------------------------------------------------- 1 | baseApiUri)); 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | public function getAccessTokenEndpoint() 34 | { 35 | return new Uri(sprintf('%s/oauth/token/', $this->baseApiUri)); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | protected function getAuthorizationMethod() 42 | { 43 | return static::AUTHORIZATION_METHOD_QUERY_STRING_V4; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function requestAccessToken($code, $state = null) 50 | { 51 | if (null !== $state) { 52 | $this->validateAuthorizationState($state); 53 | } 54 | 55 | $responseBody = $this->httpClient->retrieveResponse( 56 | $this->getAccessTokenUri($code), 57 | [], 58 | $this->getExtraOAuthHeaders(), 59 | 'GET' 60 | ); 61 | 62 | $token = $this->parseAccessTokenResponse($responseBody); 63 | $this->storage->storeAccessToken($this->service(), $token); 64 | 65 | return $token; 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | public function getAccessTokenUri($code) 72 | { 73 | $parameters = [ 74 | 'code' => $code, 75 | 'client_id' => $this->credentials->getConsumerId(), 76 | 'client_secret' => $this->credentials->getConsumerSecret(), 77 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 78 | 'grant_type' => 'authorization_code', 79 | 'scope' => $this->scopes, 80 | ]; 81 | 82 | $parameters['scope'] = implode(' ', $this->scopes); 83 | 84 | // Build the url 85 | $url = $this->getAccessTokenEndpoint(); 86 | foreach ($parameters as $key => $val) { 87 | $url->addToQuery($key, $val); 88 | } 89 | 90 | return $url; 91 | } 92 | 93 | /** 94 | * {@inheritdoc} 95 | */ 96 | protected function parseAccessTokenResponse($responseBody) 97 | { 98 | $data = json_decode($responseBody, true); 99 | 100 | if (null === $data || !is_array($data)) { 101 | throw new TokenResponseException('Unable to parse response.'); 102 | } elseif (isset($data['error'])) { 103 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 104 | } 105 | 106 | $token = new StdOAuth2Token(); 107 | $token->setAccessToken($data['access_token']); 108 | $token->setLifetime($data['expires_in']); 109 | 110 | if (isset($data['refresh_token'])) { 111 | $token->setRefreshToken($data['refresh_token']); 112 | unset($data['refresh_token']); 113 | } 114 | 115 | unset($data['access_token'], $data['expires_in']); 116 | 117 | $token->setExtraParams($data); 118 | 119 | return $token; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Box.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see https://developers.box.com/oauth/ 19 | */ 20 | class Box extends AbstractService 21 | { 22 | public function __construct( 23 | CredentialsInterface $credentials, 24 | ClientInterface $httpClient, 25 | TokenStorageInterface $storage, 26 | $scopes = [], 27 | ?UriInterface $baseApiUri = null 28 | ) { 29 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri, true); 30 | 31 | if (null === $baseApiUri) { 32 | $this->baseApiUri = new Uri('https://api.box.com/2.0/'); 33 | } 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getAuthorizationEndpoint() 40 | { 41 | return new Uri('https://www.box.com/api/oauth2/authorize'); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getAccessTokenEndpoint() 48 | { 49 | return new Uri('https://www.box.com/api/oauth2/token'); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | protected function getAuthorizationMethod() 56 | { 57 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | protected function parseAccessTokenResponse($responseBody) 64 | { 65 | $data = json_decode($responseBody, true); 66 | 67 | if (null === $data || !is_array($data)) { 68 | throw new TokenResponseException('Unable to parse response.'); 69 | } elseif (isset($data['error'])) { 70 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 71 | } 72 | 73 | $token = new StdOAuth2Token(); 74 | $token->setAccessToken($data['access_token']); 75 | $token->setLifeTime($data['expires_in']); 76 | 77 | if (isset($data['refresh_token'])) { 78 | $token->setRefreshToken($data['refresh_token']); 79 | unset($data['refresh_token']); 80 | } 81 | 82 | unset($data['access_token'], $data['expires_in']); 83 | 84 | $token->setExtraParams($data); 85 | 86 | return $token; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Dailymotion.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see http://www.dailymotion.com/doc/api/authentication.html 19 | */ 20 | class Dailymotion extends AbstractService 21 | { 22 | /** 23 | * Scopes. 24 | * 25 | * @var string 26 | */ 27 | const SCOPE_EMAIL = 'email'; 28 | const SCOPE_PROFILE = 'userinfo'; 29 | const SCOPE_VIDEOS = 'manage_videos'; 30 | const SCOPE_COMMENTS = 'manage_comments'; 31 | const SCOPE_PLAYLIST = 'manage_playlists'; 32 | const SCOPE_TILES = 'manage_tiles'; 33 | const SCOPE_SUBSCRIPTIONS = 'manage_subscriptions'; 34 | const SCOPE_FRIENDS = 'manage_friends'; 35 | const SCOPE_FAVORITES = 'manage_favorites'; 36 | const SCOPE_GROUPS = 'manage_groups'; 37 | 38 | /** 39 | * Dialog form factors. 40 | * 41 | * @var string 42 | */ 43 | const DISPLAY_PAGE = 'page'; 44 | const DISPLAY_POPUP = 'popup'; 45 | const DISPLAY_MOBILE = 'mobile'; 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function __construct( 51 | CredentialsInterface $credentials, 52 | ClientInterface $httpClient, 53 | TokenStorageInterface $storage, 54 | $scopes = [], 55 | ?UriInterface $baseApiUri = null 56 | ) { 57 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 58 | 59 | if (null === $baseApiUri) { 60 | $this->baseApiUri = new Uri('https://api.dailymotion.com/'); 61 | } 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getAuthorizationEndpoint() 68 | { 69 | return new Uri('https://api.dailymotion.com/oauth/authorize'); 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function getAccessTokenEndpoint() 76 | { 77 | return new Uri('https://api.dailymotion.com/oauth/token'); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function getAuthorizationMethod() 84 | { 85 | return static::AUTHORIZATION_METHOD_HEADER_OAUTH; 86 | } 87 | 88 | /** 89 | * {@inheritdoc} 90 | */ 91 | protected function parseAccessTokenResponse($responseBody) 92 | { 93 | $data = json_decode($responseBody, true); 94 | 95 | if (null === $data || !is_array($data)) { 96 | throw new TokenResponseException('Unable to parse response.'); 97 | } elseif (isset($data['error_description']) || isset($data['error'])) { 98 | throw new TokenResponseException( 99 | sprintf( 100 | 'Error in retrieving token: "%s"', 101 | $data['error_description'] ?? $data['error'] 102 | ) 103 | ); 104 | } 105 | 106 | $token = new StdOAuth2Token(); 107 | $token->setAccessToken($data['access_token']); 108 | $token->setLifeTime($data['expires_in']); 109 | 110 | if (isset($data['refresh_token'])) { 111 | $token->setRefreshToken($data['refresh_token']); 112 | unset($data['refresh_token']); 113 | } 114 | 115 | unset($data['access_token'], $data['expires_in']); 116 | 117 | $token->setExtraParams($data); 118 | 119 | return $token; 120 | } 121 | 122 | /** 123 | * {@inheritdoc} 124 | */ 125 | protected function getExtraOAuthHeaders() 126 | { 127 | return ['Accept' => 'application/json']; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Deezer.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see http://developers.deezer.com/api/ 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth2\Token\StdOAuth2Token; 20 | 21 | /** 22 | * Deezer service. 23 | * 24 | * @author Pedro Amorim 25 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 26 | * 27 | * @see http://developers.deezer.com/api/ 28 | */ 29 | class Deezer extends AbstractService 30 | { 31 | /** 32 | * Defined scopes 33 | * http://developers.deezer.com/api/permissions. 34 | */ 35 | const SCOPE_BASIC_ACCESS = 'basic_access'; // Access users basic information 36 | const SCOPE_EMAIL = 'email'; // Get the user's email 37 | const SCOPE_OFFLINE_ACCESS = 'offline_access'; // Access user data any time 38 | const SCOPE_MANAGE_LIBRARY = 'manage_library'; // Manage users' library 39 | const SCOPE_MANAGE_COMMUNITY = 'manage_community'; // Manage users' friends 40 | const SCOPE_DELETE_LIBRARY = 'delete_library'; // Delete library items 41 | const SCOPE_LISTENING_HISTORY = 'listening_history'; // Access the user's listening history 42 | 43 | public function __construct( 44 | CredentialsInterface $credentials, 45 | ClientInterface $httpClient, 46 | TokenStorageInterface $storage, 47 | $scopes = [], 48 | ?UriInterface $baseApiUri = null 49 | ) { 50 | parent::__construct( 51 | $credentials, 52 | $httpClient, 53 | $storage, 54 | $scopes, 55 | $baseApiUri, 56 | true 57 | ); 58 | 59 | if (null === $baseApiUri) { 60 | $this->baseApiUri = new Uri('https://api.deezer.com/'); 61 | } 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getAuthorizationEndpoint() 68 | { 69 | return new Uri('https://connect.deezer.com/oauth/auth.php'); 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function getAccessTokenEndpoint() 76 | { 77 | return new Uri('https://connect.deezer.com/oauth/access_token.php'); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function getAuthorizationMethod() 84 | { 85 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 86 | } 87 | 88 | /** 89 | * {@inheritdoc} 90 | */ 91 | protected function parseAccessTokenResponse($responseBody) 92 | { 93 | parse_str($responseBody, $data); 94 | if (null === $data || !is_array($data) || empty($data)) { 95 | throw new TokenResponseException('Unable to parse response.'); 96 | } elseif (isset($data['error'])) { 97 | throw new TokenResponseException( 98 | 'Error in retrieving token: "' . $data['error'] . '"' 99 | ); 100 | } elseif (isset($data['error_reason'])) { 101 | throw new TokenResponseException( 102 | 'Error in retrieving token: "' . $data['error_reason'] . '"' 103 | ); 104 | } 105 | 106 | $token = new StdOAuth2Token(); 107 | $token->setAccessToken($data['access_token']); 108 | $token->setLifeTime($data['expires']); 109 | 110 | // I hope one day Deezer add a refresh token :) 111 | if (isset($data['refresh_token'])) { 112 | $token->setRefreshToken($data['refresh_token']); 113 | unset($data['refresh_token']); 114 | } 115 | 116 | unset($data['access_token'], $data['expires']); 117 | 118 | $token->setExtraParams($data); 119 | 120 | return $token; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Delicious.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://github.com/SciDevs/delicious-api/blob/master/api/oauth.md 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth2\Token\StdOAuth2Token; 20 | 21 | /** 22 | * Delicious service. 23 | * 24 | * @author Pedro Amorim 25 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 26 | * 27 | * @see https://github.com/SciDevs/delicious-api/blob/master/api/oauth.md 28 | */ 29 | class Delicious extends AbstractService 30 | { 31 | public function __construct( 32 | CredentialsInterface $credentials, 33 | ClientInterface $httpClient, 34 | TokenStorageInterface $storage, 35 | $scopes = [], 36 | ?UriInterface $baseApiUri = null 37 | ) { 38 | parent::__construct( 39 | $credentials, 40 | $httpClient, 41 | $storage, 42 | $scopes, 43 | $baseApiUri, 44 | true 45 | ); 46 | 47 | if (null === $baseApiUri) { 48 | $this->baseApiUri = new Uri('https://api.del.icio.us/v1/'); 49 | } 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getAuthorizationEndpoint() 56 | { 57 | return new Uri('https://delicious.com/auth/authorize'); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getAccessTokenEndpoint() 64 | { 65 | return new Uri('https://avosapi.delicious.com/api/v1/oauth/token'); 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | protected function getAuthorizationMethod() 72 | { 73 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | protected function parseAccessTokenResponse($responseBody) 80 | { 81 | $data = json_decode($responseBody, true); 82 | 83 | if (null === $data || !is_array($data)) { 84 | throw new TokenResponseException('Unable to parse response.'); 85 | } elseif (isset($data['error'])) { 86 | throw new TokenResponseException( 87 | 'Error in retrieving token: "' . $data['error'] . '"' 88 | ); 89 | } 90 | 91 | $token = new StdOAuth2Token(); 92 | $token->setAccessToken($data['access_token']); 93 | 94 | if (isset($data['expires_in'])) { 95 | $token->setLifetime($data['expires_in']); 96 | unset($data['expires_in']); 97 | } 98 | if (isset($data['refresh_token'])) { 99 | $token->setRefreshToken($data['refresh_token']); 100 | unset($data['refresh_token']); 101 | } 102 | 103 | unset($data['access_token']); 104 | 105 | $token->setExtraParams($data); 106 | 107 | return $token; 108 | } 109 | 110 | // Special, delicious didn't respect the oauth2 RFC and need a grant_type='code' 111 | 112 | /** 113 | * {@inheritdoc} 114 | */ 115 | public function requestAccessToken($code, $state = null) 116 | { 117 | if (null !== $state) { 118 | $this->validateAuthorizationState($state); 119 | } 120 | 121 | $bodyParams = [ 122 | 'code' => $code, 123 | 'client_id' => $this->credentials->getConsumerId(), 124 | 'client_secret' => $this->credentials->getConsumerSecret(), 125 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 126 | 'grant_type' => 'code', 127 | ]; 128 | 129 | $responseBody = $this->httpClient->retrieveResponse( 130 | $this->getAccessTokenEndpoint(), 131 | $bodyParams, 132 | $this->getExtraOAuthHeaders() 133 | ); 134 | 135 | $token = $this->parseAccessTokenResponse($responseBody); 136 | $this->storage->storeAccessToken($this->service(), $token); 137 | 138 | return $token; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/DeviantArt.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://www.deviantart.com/api/v1/oauth2/'); 46 | } 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function getAuthorizationEndpoint() 53 | { 54 | return new Uri('https://www.deviantart.com/oauth2/authorize'); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function getAccessTokenEndpoint() 61 | { 62 | return new Uri('https://www.deviantart.com/oauth2/token'); 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | protected function parseAccessTokenResponse($responseBody) 69 | { 70 | $data = json_decode($responseBody, true); 71 | 72 | if (null === $data || !is_array($data)) { 73 | throw new TokenResponseException('Unable to parse response.'); 74 | } elseif (isset($data['error'])) { 75 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 76 | } 77 | 78 | $token = new StdOAuth2Token(); 79 | $token->setAccessToken($data['access_token']); 80 | 81 | if (isset($data['expires_in'])) { 82 | $token->setLifeTime($data['expires_in']); 83 | } 84 | 85 | if (isset($data['refresh_token'])) { 86 | $token->setRefreshToken($data['refresh_token']); 87 | unset($data['refresh_token']); 88 | } 89 | 90 | unset($data['access_token'], $data['expires_in']); 91 | 92 | $token->setExtraParams($data); 93 | 94 | return $token; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Dropbox.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see https://www.dropbox.com/developers/core/docs 19 | */ 20 | class Dropbox extends AbstractService 21 | { 22 | public function __construct( 23 | CredentialsInterface $credentials, 24 | ClientInterface $httpClient, 25 | TokenStorageInterface $storage, 26 | $scopes = [], 27 | ?UriInterface $baseApiUri = null 28 | ) { 29 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 30 | 31 | if (null === $baseApiUri) { 32 | $this->baseApiUri = new Uri('https://api.dropbox.com/1/'); 33 | } 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getAuthorizationUri(array $additionalParameters = []) 40 | { 41 | $parameters = array_merge( 42 | $additionalParameters, 43 | [ 44 | 'client_id' => $this->credentials->getConsumerId(), 45 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 46 | 'response_type' => 'code', 47 | ] 48 | ); 49 | 50 | $parameters['scope'] = implode(' ', $this->scopes); 51 | 52 | // Build the url 53 | $url = clone $this->getAuthorizationEndpoint(); 54 | foreach ($parameters as $key => $val) { 55 | $url->addToQuery($key, $val); 56 | } 57 | 58 | return $url; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function getAuthorizationEndpoint() 65 | { 66 | return new Uri('https://www.dropbox.com/1/oauth2/authorize'); 67 | } 68 | 69 | /** 70 | * {@inheritdoc} 71 | */ 72 | public function getAccessTokenEndpoint() 73 | { 74 | return new Uri('https://api.dropbox.com/1/oauth2/token'); 75 | } 76 | 77 | /** 78 | * {@inheritdoc} 79 | */ 80 | protected function getAuthorizationMethod() 81 | { 82 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | protected function parseAccessTokenResponse($responseBody) 89 | { 90 | $data = json_decode($responseBody, true); 91 | 92 | if (null === $data || !is_array($data)) { 93 | throw new TokenResponseException('Unable to parse response.'); 94 | } elseif (isset($data['error'])) { 95 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 96 | } 97 | 98 | $token = new StdOAuth2Token(); 99 | $token->setAccessToken($data['access_token']); 100 | 101 | if (isset($data['refresh_token'])) { 102 | $token->setRefreshToken($data['refresh_token']); 103 | unset($data['refresh_token']); 104 | } 105 | 106 | unset($data['access_token']); 107 | 108 | $token->setExtraParams($data); 109 | 110 | return $token; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/EveOnline.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | namespace OAuth\OAuth2\Service; 10 | 11 | use OAuth\Common\Consumer\CredentialsInterface; 12 | use OAuth\Common\Http\Client\ClientInterface; 13 | use OAuth\Common\Http\Exception\TokenResponseException; 14 | use OAuth\Common\Http\Uri\Uri; 15 | use OAuth\Common\Http\Uri\UriInterface; 16 | use OAuth\Common\Storage\TokenStorageInterface; 17 | use OAuth\Common\Token\TokenInterface; 18 | use OAuth\OAuth2\Token\StdOAuth2Token; 19 | 20 | /** 21 | * Class EveOnline. 22 | */ 23 | class EveOnline extends AbstractService 24 | { 25 | public function __construct( 26 | CredentialsInterface $credentials, 27 | ClientInterface $httpClient, 28 | TokenStorageInterface $storage, 29 | $scopes = [], 30 | ?UriInterface $baseApiUri = null 31 | ) { 32 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 33 | 34 | if (null === $baseApiUri) { 35 | $this->baseApiUri = new Uri('https://login.eveonline.com'); 36 | } 37 | } 38 | 39 | /** 40 | * Returns the authorization API endpoint. 41 | * 42 | * @return UriInterface 43 | */ 44 | public function getAuthorizationEndpoint() 45 | { 46 | return new Uri($this->baseApiUri . '/oauth/authorize'); 47 | } 48 | 49 | /** 50 | * Returns the access token API endpoint. 51 | * 52 | * @return UriInterface 53 | */ 54 | public function getAccessTokenEndpoint() 55 | { 56 | return new Uri($this->baseApiUri . '/oauth/token'); 57 | } 58 | 59 | /** 60 | * Parses the access token response and returns a TokenInterface. 61 | * 62 | * @param string $responseBody 63 | * 64 | * @return TokenInterface 65 | */ 66 | protected function parseAccessTokenResponse($responseBody) 67 | { 68 | $data = json_decode($responseBody, true); 69 | 70 | if (null === $data || !is_array($data)) { 71 | throw new TokenResponseException('Unable to parse response.'); 72 | } elseif (isset($data['error_description'])) { 73 | throw new TokenResponseException('Error in retrieving token: "' . $data['error_description'] . '"'); 74 | } elseif (isset($data['error'])) { 75 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 76 | } 77 | 78 | $token = new StdOAuth2Token(); 79 | $token->setAccessToken($data['access_token']); 80 | $token->setLifeTime($data['expires_in']); 81 | 82 | if (isset($data['refresh_token'])) { 83 | $token->setRefreshToken($data['refresh_token']); 84 | unset($data['refresh_token']); 85 | } 86 | 87 | unset($data['access_token'], $data['expires_in']); 88 | 89 | $token->setExtraParams($data); 90 | 91 | return $token; 92 | } 93 | 94 | /** 95 | * {@inheritdoc} 96 | */ 97 | protected function getAuthorizationMethod() 98 | { 99 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Exception/InvalidAccessTypeException.php: -------------------------------------------------------------------------------- 1 | 5 | * Released under the MIT license. 6 | */ 7 | 8 | namespace OAuth\OAuth2\Service\Exception; 9 | 10 | use OAuth\Common\Exception\Exception; 11 | 12 | /** 13 | * Exception thrown when a scope provided to a service is invalid. 14 | */ 15 | class InvalidScopeException extends Exception 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Exception/MissingRefreshTokenException.php: -------------------------------------------------------------------------------- 1 | 5 | * Released under the MIT license. 6 | */ 7 | 8 | namespace OAuth\OAuth2\Service\Exception; 9 | 10 | use OAuth\Common\Exception\Exception; 11 | 12 | /** 13 | * Exception thrown when service is requested to refresh the access token but no refresh token can be found. 14 | */ 15 | class MissingRefreshTokenException extends Exception 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Foursquare.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.foursquare.com/v2/'); 28 | } 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function getAuthorizationEndpoint() 35 | { 36 | return new Uri('https://foursquare.com/oauth2/authenticate'); 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getAccessTokenEndpoint() 43 | { 44 | return new Uri('https://foursquare.com/oauth2/access_token'); 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | protected function parseAccessTokenResponse($responseBody) 51 | { 52 | $data = json_decode($responseBody, true); 53 | 54 | if (null === $data || !is_array($data)) { 55 | throw new TokenResponseException('Unable to parse response.'); 56 | } elseif (isset($data['error'])) { 57 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 58 | } 59 | 60 | $token = new StdOAuth2Token(); 61 | $token->setAccessToken($data['access_token']); 62 | // Foursquare tokens evidently never expire... 63 | $token->setEndOfLife(StdOAuth2Token::EOL_NEVER_EXPIRES); 64 | unset($data['access_token']); 65 | 66 | $token->setExtraParams($data); 67 | 68 | return $token; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function request($path, $method = 'GET', $body = null, array $extraHeaders = []) 75 | { 76 | $uri = $this->determineRequestUriFromPath($path, $this->baseApiUri); 77 | $uri->addToQuery('v', $this->apiVersionDate); 78 | 79 | return parent::request($uri, $method, $body, $extraHeaders); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Heroku.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see https://devcenter.heroku.com/articles/oauth 19 | */ 20 | class Heroku extends AbstractService 21 | { 22 | /** 23 | * Defined scopes. 24 | * 25 | * @see https://devcenter.heroku.com/articles/oauth#scopes 26 | */ 27 | const SCOPE_GLOBAL = 'global'; 28 | const SCOPE_IDENTITY = 'identity'; 29 | const SCOPE_READ = 'read'; 30 | const SCOPE_WRITE = 'write'; 31 | const SCOPE_READ_PROTECTED = 'read-protected'; 32 | const SCOPE_WRITE_PROTECTED = 'write-protected'; 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function __construct( 38 | CredentialsInterface $credentials, 39 | ClientInterface $httpClient, 40 | TokenStorageInterface $storage, 41 | $scopes = [], 42 | ?UriInterface $baseApiUri = null 43 | ) { 44 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 45 | 46 | if (null === $baseApiUri) { 47 | $this->baseApiUri = new Uri('https://api.heroku.com/'); 48 | } 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function getAuthorizationEndpoint() 55 | { 56 | return new Uri('https://id.heroku.com/oauth/authorize'); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function getAccessTokenEndpoint() 63 | { 64 | return new Uri('https://id.heroku.com/oauth/token'); 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | protected function getAuthorizationMethod() 71 | { 72 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | protected function parseAccessTokenResponse($responseBody) 79 | { 80 | $data = json_decode($responseBody, true); 81 | 82 | if (null === $data || !is_array($data)) { 83 | throw new TokenResponseException('Unable to parse response.'); 84 | } elseif (isset($data['error_description']) || isset($data['error'])) { 85 | throw new TokenResponseException( 86 | sprintf( 87 | 'Error in retrieving token: "%s"', 88 | $data['error_description'] ?? $data['error'] 89 | ) 90 | ); 91 | } 92 | 93 | $token = new StdOAuth2Token(); 94 | $token->setAccessToken($data['access_token']); 95 | $token->setLifeTime($data['expires_in']); 96 | 97 | if (isset($data['refresh_token'])) { 98 | $token->setRefreshToken($data['refresh_token']); 99 | unset($data['refresh_token']); 100 | } 101 | 102 | unset($data['access_token'], $data['expires_in']); 103 | 104 | $token->setExtraParams($data); 105 | 106 | return $token; 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | protected function getExtraOAuthHeaders() 113 | { 114 | return ['Accept' => 'application/vnd.heroku+json; version=3']; 115 | } 116 | 117 | /** 118 | * {@inheritdoc} 119 | */ 120 | protected function getExtraApiHeaders() 121 | { 122 | return ['Accept' => 'application/vnd.heroku+json; version=3', 'Content-Type' => 'application/json']; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Instagram.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.instagram.com/v1/'); 38 | } 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function getAuthorizationEndpoint() 45 | { 46 | return new Uri('https://api.instagram.com/oauth/authorize/'); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function getAccessTokenEndpoint() 53 | { 54 | return new Uri('https://api.instagram.com/oauth/access_token'); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | protected function getAuthorizationMethod() 61 | { 62 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | protected function parseAccessTokenResponse($responseBody) 69 | { 70 | $data = json_decode($responseBody, true); 71 | 72 | if (null === $data || !is_array($data)) { 73 | throw new TokenResponseException('Unable to parse response.'); 74 | } elseif (isset($data['error'])) { 75 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 76 | } 77 | 78 | $token = new StdOAuth2Token(); 79 | $token->setAccessToken($data['access_token']); 80 | // Instagram tokens evidently never expire... 81 | $token->setEndOfLife(StdOAuth2Token::EOL_NEVER_EXPIRES); 82 | unset($data['access_token']); 83 | 84 | $token->setExtraParams($data); 85 | 86 | return $token; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Linkedin.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see http://developer.linkedin.com/documents/authentication 19 | */ 20 | class Linkedin extends AbstractService 21 | { 22 | /** 23 | * Defined scopes. 24 | * 25 | * @see https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow?context=linkedin/context 26 | */ 27 | const SCOPE_R_LITEPROFILE = 'r_liteprofile'; 28 | const SCOPE_R_FULLPROFILE = 'r_fullprofile'; 29 | const SCOPE_R_EMAILADDRESS = 'r_emailaddress'; 30 | const SCOPE_R_NETWORK = 'r_network'; 31 | const SCOPE_R_CONTACTINFO = 'r_contactinfo'; 32 | const SCOPE_RW_NUS = 'rw_nus'; 33 | const SCOPE_RW_COMPANY_ADMIN = 'rw_company_admin'; 34 | const SCOPE_RW_GROUPS = 'rw_groups'; 35 | const SCOPE_W_MESSAGES = 'w_messages'; 36 | const SCOPE_W_MEMBER_SOCIAL = 'w_member_social'; 37 | 38 | public function __construct( 39 | CredentialsInterface $credentials, 40 | ClientInterface $httpClient, 41 | TokenStorageInterface $storage, 42 | $scopes = [], 43 | ?UriInterface $baseApiUri = null 44 | ) { 45 | if (count($scopes) === 0) { 46 | $scopes = [self::SCOPE_R_LITEPROFILE, self::SCOPE_R_EMAILADDRESS]; 47 | } 48 | 49 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri, true); 50 | 51 | if (null === $baseApiUri) { 52 | $this->baseApiUri = new Uri('https://api.linkedin.com/v2/'); 53 | } 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function getAuthorizationEndpoint() 60 | { 61 | return new Uri('https://www.linkedin.com/oauth/v2/authorization'); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getAccessTokenEndpoint() 68 | { 69 | return new Uri('https://www.linkedin.com/oauth/v2/accessToken'); 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | protected function getAuthorizationMethod() 76 | { 77 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function parseAccessTokenResponse($responseBody) 84 | { 85 | $data = json_decode($responseBody, true); 86 | 87 | if (null === $data || !is_array($data)) { 88 | throw new TokenResponseException('Unable to parse response.'); 89 | } elseif (isset($data['error'])) { 90 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 91 | } 92 | 93 | $token = new StdOAuth2Token(); 94 | $token->setAccessToken($data['access_token']); 95 | $token->setLifeTime($data['expires_in']); 96 | 97 | if (isset($data['refresh_token'])) { 98 | $token->setRefreshToken($data['refresh_token']); 99 | unset($data['refresh_token']); 100 | } 101 | 102 | unset($data['access_token'], $data['expires_in']); 103 | 104 | $token->setExtraParams($data); 105 | 106 | return $token; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Mailchimp.php: -------------------------------------------------------------------------------- 1 | baseApiUri && $storage->hasAccessToken($this->service())) { 25 | $this->setBaseApiUri($storage->retrieveAccessToken($this->service())); 26 | } 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | protected function getAuthorizationMethod() 33 | { 34 | return static::AUTHORIZATION_METHOD_QUERY_STRING_V3; 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAuthorizationEndpoint() 41 | { 42 | return new Uri('https://login.mailchimp.com/oauth2/authorize'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function getAccessTokenEndpoint() 49 | { 50 | return new Uri('https://login.mailchimp.com/oauth2/token'); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function parseAccessTokenResponse($responseBody) 57 | { 58 | // Parse JSON 59 | $data = json_decode($responseBody, true); 60 | 61 | // Do validation. 62 | if (null === $data || !is_array($data)) { 63 | throw new TokenResponseException('Unable to parse response.'); 64 | } elseif (isset($data['error'])) { 65 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 66 | } 67 | 68 | // Create token object. 69 | $token = new StdOAuth2Token($data['access_token']); 70 | 71 | // Set the right API endpoint. 72 | $this->setBaseApiUri($token); 73 | 74 | // Mailchimp tokens evidently never expire... 75 | $token->setEndOfLife(StdOAuth2Token::EOL_NEVER_EXPIRES); 76 | 77 | return $token; 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | public function request($path, $method = 'GET', $body = null, array $extraHeaders = []) 84 | { 85 | if (null === $this->baseApiUri) { 86 | $this->setBaseApiUri($this->storage->retrieveAccessToken($this->service())); 87 | } 88 | 89 | return parent::request($path, $method, $body, $extraHeaders); 90 | } 91 | 92 | /** 93 | * Set the right base endpoint. 94 | */ 95 | protected function setBaseApiUri(StdOAuth2Token $token) 96 | { 97 | // Make request uri. 98 | $endpoint = 'https://login.mailchimp.com/oauth2/metadata?oauth_token=' . $token->getAccessToken(); 99 | 100 | // Grab meta data about the token. 101 | $response = $this->httpClient->retrieveResponse(new Uri($endpoint), [], [], 'GET'); 102 | 103 | // Parse JSON. 104 | $meta = json_decode($response, true); 105 | 106 | // Set base api uri. 107 | $this->baseApiUri = new Uri('https://' . $meta['dc'] . '.api.mailchimp.com/2.0/'); 108 | 109 | // Allow chaining. 110 | return $this; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Microsoft.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://apis.live.net/v5.0/'); 64 | } 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function getAuthorizationEndpoint() 71 | { 72 | return new Uri('https://login.live.com/oauth20_authorize.srf'); 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | public function getAccessTokenEndpoint() 79 | { 80 | return new Uri('https://login.live.com/oauth20_token.srf'); 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | public function getAuthorizationMethod() 87 | { 88 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 89 | } 90 | 91 | /** 92 | * {@inheritdoc} 93 | */ 94 | protected function parseAccessTokenResponse($responseBody) 95 | { 96 | $data = json_decode($responseBody, true); 97 | 98 | if (null === $data || !is_array($data)) { 99 | throw new TokenResponseException('Unable to parse response.'); 100 | } elseif (isset($data['error'])) { 101 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 102 | } 103 | 104 | $token = new StdOAuth2Token(); 105 | $token->setAccessToken($data['access_token']); 106 | $token->setLifetime($data['expires_in']); 107 | 108 | if (isset($data['refresh_token'])) { 109 | $token->setRefreshToken($data['refresh_token']); 110 | unset($data['refresh_token']); 111 | } 112 | 113 | unset($data['access_token'], $data['expires_in']); 114 | 115 | $token->setExtraParams($data); 116 | 117 | return $token; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Mondo.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.getmondo.co.uk'); 26 | } 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function getAuthorizationEndpoint() 33 | { 34 | return new Uri('https://auth.getmondo.co.uk'); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAccessTokenEndpoint() 41 | { 42 | return new Uri('https://api.getmondo.co.uk/oauth2/token'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | protected function getAuthorizationMethod() 49 | { 50 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function parseAccessTokenResponse($responseBody) 57 | { 58 | $data = json_decode($responseBody, true); 59 | 60 | if (null === $data || !is_array($data)) { 61 | throw new TokenResponseException('Unable to parse response.'); 62 | } elseif (isset($data['error'])) { 63 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 64 | } 65 | 66 | $token = new StdOAuth2Token(); 67 | $token->setAccessToken($data['access_token']); 68 | 69 | if (isset($data['expires_in'])) { 70 | $token->setLifetime($data['expires_in']); 71 | unset($data['expires_in']); 72 | } 73 | 74 | if (isset($data['refresh_token'])) { 75 | $token->setRefreshToken($data['refresh_token']); 76 | unset($data['refresh_token']); 77 | } 78 | 79 | unset($data['access_token']); 80 | 81 | $token->setExtraParams($data); 82 | 83 | return $token; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Nest.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://developer.nest.com/documentation 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth2\Token\StdOAuth2Token; 20 | 21 | /** 22 | * Nest service. 23 | * 24 | * @author Pedro Amorim 25 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 26 | * 27 | * @see https://developer.nest.com/documentation 28 | */ 29 | class Nest extends AbstractService 30 | { 31 | public function __construct( 32 | CredentialsInterface $credentials, 33 | ClientInterface $httpClient, 34 | TokenStorageInterface $storage, 35 | $scopes = [], 36 | ?UriInterface $baseApiUri = null 37 | ) { 38 | parent::__construct( 39 | $credentials, 40 | $httpClient, 41 | $storage, 42 | $scopes, 43 | $baseApiUri, 44 | true 45 | ); 46 | 47 | if (null === $baseApiUri) { 48 | $this->baseApiUri = new Uri('https://developer-api.nest.com/'); 49 | } 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getAuthorizationEndpoint() 56 | { 57 | return new Uri('https://home.nest.com/login/oauth2'); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getAccessTokenEndpoint() 64 | { 65 | return new Uri('https://api.home.nest.com/oauth2/access_token'); 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | protected function getAuthorizationMethod() 72 | { 73 | return static::AUTHORIZATION_METHOD_QUERY_STRING_V4; 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | protected function parseAccessTokenResponse($responseBody) 80 | { 81 | $data = json_decode($responseBody, true); 82 | 83 | if (null === $data || !is_array($data)) { 84 | throw new TokenResponseException('Unable to parse response.'); 85 | } elseif (isset($data['error'])) { 86 | throw new TokenResponseException( 87 | 'Error in retrieving token: "' . $data['error'] . '"' 88 | ); 89 | } 90 | 91 | $token = new StdOAuth2Token(); 92 | $token->setAccessToken($data['access_token']); 93 | $token->setLifeTime($data['expires_in']); 94 | 95 | if (isset($data['refresh_token'])) { 96 | $token->setRefreshToken($data['refresh_token']); 97 | unset($data['refresh_token']); 98 | } 99 | 100 | unset($data['access_token'], $data['expires_in']); 101 | 102 | $token->setExtraParams($data); 103 | 104 | return $token; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Netatmo.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://dev.netatmo.com/doc/ 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth2\Token\StdOAuth2Token; 20 | 21 | /** 22 | * Netatmo service. 23 | * 24 | * @author Pedro Amorim 25 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 26 | * 27 | * @see https://dev.netatmo.com/doc/ 28 | */ 29 | class Netatmo extends AbstractService 30 | { 31 | /** 32 | * SCOPES. 33 | * 34 | * @see https://dev.netatmo.com/doc/authentication/scopes 35 | */ 36 | 37 | // Used to read weather station's data (devicelist, getmeasure) 38 | const SCOPE_STATION_READ = 'read_station'; 39 | // Used to read thermostat's data (devicelist, getmeasure, getthermstate) 40 | const SCOPE_THERMOSTAT_READ = 'read_thermostat'; 41 | // Used to configure the thermostat (syncschedule, setthermpoint) 42 | const SCOPE_THERMOSTAT_WRITE = 'write_thermostat'; 43 | 44 | public function __construct( 45 | CredentialsInterface $credentials, 46 | ClientInterface $httpClient, 47 | TokenStorageInterface $storage, 48 | $scopes = [], 49 | ?UriInterface $baseApiUri = null 50 | ) { 51 | parent::__construct( 52 | $credentials, 53 | $httpClient, 54 | $storage, 55 | $scopes, 56 | $baseApiUri, 57 | true // use parameter state 58 | ); 59 | 60 | if (null === $baseApiUri) { 61 | $this->baseApiUri = new Uri('https://api.netatmo.net/'); 62 | } 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function getAuthorizationEndpoint() 69 | { 70 | return new Uri($this->baseApiUri . 'oauth2/authorize'); 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | public function getAccessTokenEndpoint() 77 | { 78 | return new Uri($this->baseApiUri . 'oauth2/token'); 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | */ 84 | protected function getAuthorizationMethod() 85 | { 86 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 87 | } 88 | 89 | /** 90 | * {@inheritdoc} 91 | */ 92 | protected function parseAccessTokenResponse($responseBody) 93 | { 94 | $data = json_decode($responseBody, true); 95 | 96 | if (null === $data || !is_array($data)) { 97 | throw new TokenResponseException('Unable to parse response.'); 98 | } elseif (isset($data['error'])) { 99 | throw new TokenResponseException( 100 | 'Error in retrieving token: "' . $data['error'] . '"' 101 | ); 102 | } 103 | 104 | $token = new StdOAuth2Token(); 105 | $token->setAccessToken($data['access_token']); 106 | $token->setLifetime($data['expires_in']); 107 | 108 | if (isset($data['refresh_token'])) { 109 | $token->setRefreshToken($data['refresh_token']); 110 | unset($data['refresh_token']); 111 | } 112 | 113 | unset($data['access_token'], $data['expires_in']); 114 | 115 | $token->setExtraParams($data); 116 | 117 | return $token; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/ParrotFlowerPower.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://flowerpowerdev.parrot.com/projects/flower-power-web-service-api/wiki 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\Common\Token\TokenInterface; 20 | use OAuth\OAuth2\Service\Exception\MissingRefreshTokenException; 21 | use OAuth\OAuth2\Token\StdOAuth2Token; 22 | 23 | /** 24 | * ParrotFlowerPower service. 25 | * 26 | * @author Pedro Amorim 27 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 28 | * 29 | * @see https://flowerpowerdev.parrot.com/projects/flower-power-web-service-api/wiki 30 | */ 31 | class ParrotFlowerPower extends AbstractService 32 | { 33 | public function __construct( 34 | CredentialsInterface $credentials, 35 | ClientInterface $httpClient, 36 | TokenStorageInterface $storage, 37 | $scopes = [], 38 | ?UriInterface $baseApiUri = null 39 | ) { 40 | parent::__construct( 41 | $credentials, 42 | $httpClient, 43 | $storage, 44 | $scopes, 45 | $baseApiUri, 46 | true 47 | ); 48 | 49 | if (null === $baseApiUri) { 50 | $this->baseApiUri = new Uri('https://apiflowerpower.parrot.com/'); 51 | } 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getAuthorizationEndpoint() 58 | { 59 | return new Uri($this->baseApiUri . 'oauth2/v1/authorize'); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | public function getAccessTokenEndpoint() 66 | { 67 | return new Uri($this->baseApiUri . 'user/v1/authenticate'); 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function getAuthorizationMethod() 74 | { 75 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | */ 81 | protected function parseAccessTokenResponse($responseBody) 82 | { 83 | $data = json_decode($responseBody, true); 84 | 85 | if (null === $data || !is_array($data)) { 86 | throw new TokenResponseException('Unable to parse response.'); 87 | } elseif (isset($data['error'])) { 88 | throw new TokenResponseException( 89 | 'Error in retrieving token: "' . $data['error'] . '"' 90 | ); 91 | } 92 | 93 | $token = new StdOAuth2Token(); 94 | $token->setAccessToken($data['access_token']); 95 | $token->setLifetime($data['expires_in']); 96 | 97 | if (isset($data['refresh_token'])) { 98 | $token->setRefreshToken($data['refresh_token']); 99 | unset($data['refresh_token']); 100 | } 101 | 102 | unset($data['access_token'], $data['expires_in']); 103 | 104 | $token->setExtraParams($data); 105 | 106 | return $token; 107 | } 108 | 109 | /** 110 | * Parrot use a different endpoint for refresh a token. 111 | * 112 | * {@inheritdoc} 113 | */ 114 | public function refreshAccessToken(TokenInterface $token) 115 | { 116 | $refreshToken = $token->getRefreshToken(); 117 | 118 | if (empty($refreshToken)) { 119 | throw new MissingRefreshTokenException(); 120 | } 121 | 122 | $parameters = [ 123 | 'grant_type' => 'refresh_token', 124 | 'type' => 'web_server', 125 | 'client_id' => $this->credentials->getConsumerId(), 126 | 'client_secret' => $this->credentials->getConsumerSecret(), 127 | 'refresh_token' => $refreshToken, 128 | ]; 129 | 130 | $responseBody = $this->httpClient->retrieveResponse( 131 | new Uri($this->baseApiUri . 'user/v1/refresh'), 132 | $parameters, 133 | $this->getExtraOAuthHeaders() 134 | ); 135 | $token = $this->parseAccessTokenResponse($responseBody); 136 | $this->storage->storeAccessToken($this->service(), $token); 137 | 138 | return $token; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Paypal.php: -------------------------------------------------------------------------------- 1 | 17 | * 18 | * @see https://developer.paypal.com/webapps/developer/docs/integration/direct/log-in-with-paypal/detailed/ 19 | */ 20 | class Paypal extends AbstractService 21 | { 22 | /** 23 | * Defined scopes. 24 | * 25 | * @see https://developer.paypal.com/webapps/developer/docs/integration/direct/log-in-with-paypal/detailed/ 26 | * @see #attributes 27 | */ 28 | const SCOPE_OPENID = 'openid'; 29 | const SCOPE_PROFILE = 'profile'; 30 | const SCOPE_PAYPALATTRIBUTES = 'https://uri.paypal.com/services/paypalattributes'; 31 | const SCOPE_EMAIL = 'email'; 32 | const SCOPE_ADDRESS = 'address'; 33 | const SCOPE_PHONE = 'phone'; 34 | const SCOPE_EXPRESSCHECKOUT = 'https://uri.paypal.com/services/expresscheckout'; 35 | 36 | public function __construct( 37 | CredentialsInterface $credentials, 38 | ClientInterface $httpClient, 39 | TokenStorageInterface $storage, 40 | $scopes = [], 41 | ?UriInterface $baseApiUri = null 42 | ) { 43 | parent::__construct($credentials, $httpClient, $storage, $scopes, $baseApiUri); 44 | 45 | if (null === $baseApiUri) { 46 | $this->baseApiUri = new Uri('https://api.paypal.com/v1/'); 47 | } 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function getAuthorizationEndpoint() 54 | { 55 | return new Uri('https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize'); 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | public function getAccessTokenEndpoint() 62 | { 63 | return new Uri('https://api.paypal.com/v1/identity/openidconnect/tokenservice'); 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | */ 69 | protected function getAuthorizationMethod() 70 | { 71 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | protected function parseAccessTokenResponse($responseBody) 78 | { 79 | $data = json_decode($responseBody, true); 80 | 81 | if (null === $data || !is_array($data)) { 82 | throw new TokenResponseException('Unable to parse response.'); 83 | } elseif (isset($data['message'])) { 84 | throw new TokenResponseException('Error in retrieving token: "' . $data['message'] . '"'); 85 | } elseif (isset($data['name'])) { 86 | throw new TokenResponseException('Error in retrieving token: "' . $data['name'] . '"'); 87 | } 88 | 89 | $token = new StdOAuth2Token(); 90 | $token->setAccessToken($data['access_token']); 91 | $token->setLifeTime($data['expires_in']); 92 | 93 | if (isset($data['refresh_token'])) { 94 | $token->setRefreshToken($data['refresh_token']); 95 | unset($data['refresh_token']); 96 | } 97 | 98 | unset($data['access_token'], $data['expires_in']); 99 | 100 | $token->setExtraParams($data); 101 | 102 | return $token; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Pinterest.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 7 | * 8 | * @see https://developers.pinterest.com/docs/api/overview/ 9 | */ 10 | 11 | namespace OAuth\OAuth2\Service; 12 | 13 | use OAuth\Common\Consumer\CredentialsInterface; 14 | use OAuth\Common\Http\Client\ClientInterface; 15 | use OAuth\Common\Http\Exception\TokenResponseException; 16 | use OAuth\Common\Http\Uri\Uri; 17 | use OAuth\Common\Http\Uri\UriInterface; 18 | use OAuth\Common\Storage\TokenStorageInterface; 19 | use OAuth\OAuth2\Token\StdOAuth2Token; 20 | 21 | /** 22 | * Pinterest service. 23 | * 24 | * @author Pedro Amorim 25 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 26 | * 27 | * @see https://developers.pinterest.com/docs/api/overview/ 28 | */ 29 | class Pinterest extends AbstractService 30 | { 31 | /** 32 | * Defined scopes - More scopes are listed here: 33 | * https://developers.pinterest.com/docs/api/overview/. 34 | */ 35 | const SCOPE_READ_PUBLIC = 'read_public'; // read a user’s Pins, boards and likes 36 | const SCOPE_WRITE_PUBLIC = 'write_public'; // write Pins, boards, likes 37 | const SCOPE_READ_RELATIONSHIPS = 'read_relationships'; // read a user’s follows (boards, users, interests) 38 | const SCOPE_WRITE_RELATIONSHIPS = 'write_relationships'; // follow boards, users and interests 39 | 40 | public function __construct( 41 | CredentialsInterface $credentials, 42 | ClientInterface $httpClient, 43 | TokenStorageInterface $storage, 44 | $scopes = [], 45 | ?UriInterface $baseApiUri = null 46 | ) { 47 | parent::__construct( 48 | $credentials, 49 | $httpClient, 50 | $storage, 51 | $scopes, 52 | $baseApiUri, 53 | true 54 | ); 55 | 56 | if (null === $baseApiUri) { 57 | $this->baseApiUri = new Uri('https://api.pinterest.com/'); 58 | } 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function getAuthorizationEndpoint() 65 | { 66 | return new Uri('https://api.pinterest.com/oauth/'); 67 | } 68 | 69 | /** 70 | * {@inheritdoc} 71 | */ 72 | public function getAccessTokenEndpoint() 73 | { 74 | return new Uri('https://api.pinterest.com/v1/oauth/token'); 75 | } 76 | 77 | /** 78 | * {@inheritdoc} 79 | */ 80 | protected function getAuthorizationMethod() 81 | { 82 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | protected function parseAccessTokenResponse($responseBody) 89 | { 90 | $data = json_decode($responseBody, true); 91 | 92 | if (null === $data || !is_array($data)) { 93 | throw new TokenResponseException('Unable to parse response.'); 94 | } elseif (isset($data['error'])) { 95 | throw new TokenResponseException( 96 | 'Error in retrieving token: "' . $data['error'] . '"' 97 | ); 98 | } 99 | 100 | $token = new StdOAuth2Token(); 101 | $token->setAccessToken($data['access_token']); 102 | 103 | if (isset($data['expires_in'])) { 104 | $token->setLifeTime($data['expires_in']); 105 | unset($data['expires_in']); 106 | } 107 | // I hope one day Pinterest add a refresh token :) 108 | if (isset($data['refresh_token'])) { 109 | $token->setRefreshToken($data['refresh_token']); 110 | unset($data['refresh_token']); 111 | } 112 | 113 | unset($data['access_token']); 114 | 115 | $token->setExtraParams($data); 116 | 117 | return $token; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Pocket.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://getpocket.com/v3/'); 25 | } 26 | } 27 | 28 | public function getRequestTokenEndpoint() 29 | { 30 | return new Uri('https://getpocket.com/v3/oauth/request'); 31 | } 32 | 33 | public function getAuthorizationEndpoint() 34 | { 35 | return new Uri('https://getpocket.com/auth/authorize'); 36 | } 37 | 38 | public function getAccessTokenEndpoint() 39 | { 40 | return new Uri('https://getpocket.com/v3/oauth/authorize'); 41 | } 42 | 43 | public function getAuthorizationUri(array $additionalParameters = []) 44 | { 45 | $parameters = array_merge( 46 | $additionalParameters, 47 | [ 48 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 49 | ] 50 | ); 51 | 52 | // Build the url 53 | $url = clone $this->getAuthorizationEndpoint(); 54 | foreach ($parameters as $key => $val) { 55 | $url->addToQuery($key, $val); 56 | } 57 | 58 | return $url; 59 | } 60 | 61 | public function requestRequestToken() 62 | { 63 | $responseBody = $this->httpClient->retrieveResponse( 64 | $this->getRequestTokenEndpoint(), 65 | [ 66 | 'consumer_key' => $this->credentials->getConsumerId(), 67 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 68 | ] 69 | ); 70 | 71 | $code = $this->parseRequestTokenResponse($responseBody); 72 | 73 | return $code; 74 | } 75 | 76 | protected function parseRequestTokenResponse($responseBody) 77 | { 78 | parse_str($responseBody, $data); 79 | 80 | if (null === $data || !is_array($data)) { 81 | throw new TokenResponseException('Unable to parse response.'); 82 | } elseif (!isset($data['code'])) { 83 | throw new TokenResponseException('Error in retrieving code.'); 84 | } 85 | 86 | return $data['code']; 87 | } 88 | 89 | public function requestAccessToken($code, $state = null) 90 | { 91 | $bodyParams = [ 92 | 'consumer_key' => $this->credentials->getConsumerId(), 93 | 'code' => $code, 94 | ]; 95 | 96 | $responseBody = $this->httpClient->retrieveResponse( 97 | $this->getAccessTokenEndpoint(), 98 | $bodyParams, 99 | $this->getExtraOAuthHeaders() 100 | ); 101 | $token = $this->parseAccessTokenResponse($responseBody); 102 | $this->storage->storeAccessToken($this->service(), $token); 103 | 104 | return $token; 105 | } 106 | 107 | protected function parseAccessTokenResponse($responseBody) 108 | { 109 | parse_str($responseBody, $data); 110 | 111 | if ($data === null || !is_array($data)) { 112 | throw new TokenResponseException('Unable to parse response.'); 113 | } elseif (isset($data['error'])) { 114 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 115 | } 116 | 117 | $token = new StdOAuth2Token(); 118 | //$token->setRequestToken($data['access_token']); 119 | $token->setAccessToken($data['access_token']); 120 | $token->setEndOfLife(StdOAuth2Token::EOL_NEVER_EXPIRES); 121 | unset($data['access_token']); 122 | $token->setExtraParams($data); 123 | 124 | return $token; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Reddit.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://oauth.reddit.com'); 48 | } 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function getAuthorizationEndpoint() 55 | { 56 | return new Uri('https://ssl.reddit.com/api/v1/authorize'); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function getAccessTokenEndpoint() 63 | { 64 | return new Uri('https://ssl.reddit.com/api/v1/access_token'); 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | protected function getAuthorizationMethod() 71 | { 72 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | protected function parseAccessTokenResponse($responseBody) 79 | { 80 | $data = json_decode($responseBody, true); 81 | 82 | if (null === $data || !is_array($data)) { 83 | throw new TokenResponseException('Unable to parse response.'); 84 | } elseif (isset($data['error'])) { 85 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 86 | } 87 | 88 | $token = new StdOAuth2Token(); 89 | $token->setAccessToken($data['access_token']); 90 | $token->setLifeTime($data['expires_in']); 91 | 92 | if (isset($data['refresh_token'])) { 93 | $token->setRefreshToken($data['refresh_token']); 94 | unset($data['refresh_token']); 95 | } 96 | 97 | unset($data['access_token'], $data['expires_in']); 98 | 99 | $token->setExtraParams($data); 100 | 101 | return $token; 102 | } 103 | 104 | /** 105 | * {@inheritdoc} 106 | */ 107 | protected function getExtraOAuthHeaders() 108 | { 109 | // Reddit uses a Basic OAuth header 110 | return ['Authorization' => 'Basic ' . 111 | base64_encode($this->credentials->getConsumerId() . ':' . $this->credentials->getConsumerSecret()), ]; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/RunKeeper.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.runkeeper.com/'); 31 | } 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function getAuthorizationUri(array $additionalParameters = []) 38 | { 39 | $parameters = array_merge( 40 | $additionalParameters, 41 | [ 42 | 'client_id' => $this->credentials->getConsumerId(), 43 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 44 | 'response_type' => 'code', 45 | ] 46 | ); 47 | 48 | $parameters['scope'] = implode(' ', $this->scopes); 49 | 50 | // Build the url 51 | $url = clone $this->getAuthorizationEndpoint(); 52 | foreach ($parameters as $key => $val) { 53 | $url->addToQuery($key, $val); 54 | } 55 | 56 | return $url; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function getAuthorizationEndpoint() 63 | { 64 | return new Uri('https://runkeeper.com/apps/authorize'); 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function getAccessTokenEndpoint() 71 | { 72 | return new Uri('https://runkeeper.com/apps/token'); 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | protected function getAuthorizationMethod() 79 | { 80 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | protected function parseAccessTokenResponse($responseBody) 87 | { 88 | $data = json_decode($responseBody, true); 89 | 90 | if (null === $data || !is_array($data)) { 91 | throw new TokenResponseException('Unable to parse response.'); 92 | } elseif (isset($data['error'])) { 93 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 94 | } 95 | 96 | $token = new StdOAuth2Token(); 97 | $token->setAccessToken($data['access_token']); 98 | 99 | unset($data['access_token']); 100 | 101 | $token->setExtraParams($data); 102 | 103 | return $token; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Salesforce.php: -------------------------------------------------------------------------------- 1 | parseAccessTokenResponse($responseBody); 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | protected function parseAccessTokenResponse($responseBody) 55 | { 56 | $data = json_decode($responseBody, true); 57 | 58 | if (null === $data || !is_array($data)) { 59 | throw new TokenResponseException('Unable to parse response.'); 60 | } elseif (isset($data['error'])) { 61 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 62 | } 63 | 64 | $token = new StdOAuth2Token(); 65 | $token->setAccessToken($data['access_token']); 66 | $token->setEndOfLife(StdOAuth2Token::EOL_UNKNOWN); 67 | unset($data['access_token']); 68 | 69 | if (isset($data['refresh_token'])) { 70 | $token->setRefreshToken($data['refresh_token']); 71 | unset($data['refresh_token']); 72 | } 73 | 74 | $token->setExtraParams($data); 75 | 76 | return $token; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | protected function getExtraOAuthHeaders() 83 | { 84 | return ['Accept' => 'application/json']; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/ServiceInterface.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.soundcloud.com/'); 26 | } 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function getAuthorizationEndpoint() 33 | { 34 | return new Uri('https://soundcloud.com/connect'); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAccessTokenEndpoint() 41 | { 42 | return new Uri('https://api.soundcloud.com/oauth2/token'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | protected function parseAccessTokenResponse($responseBody) 49 | { 50 | $data = json_decode($responseBody, true); 51 | 52 | if (null === $data || !is_array($data)) { 53 | throw new TokenResponseException('Unable to parse response.'); 54 | } elseif (isset($data['error'])) { 55 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 56 | } 57 | 58 | $token = new StdOAuth2Token(); 59 | $token->setAccessToken($data['access_token']); 60 | 61 | if (isset($data['expires_in'])) { 62 | $token->setLifetime($data['expires_in']); 63 | unset($data['expires_in']); 64 | } 65 | 66 | if (isset($data['refresh_token'])) { 67 | $token->setRefreshToken($data['refresh_token']); 68 | unset($data['refresh_token']); 69 | } 70 | 71 | unset($data['access_token']); 72 | 73 | $token->setExtraParams($data); 74 | 75 | return $token; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Spotify.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.spotify.com/v1/'); 43 | } 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getAuthorizationEndpoint() 50 | { 51 | return new Uri('https://accounts.spotify.com/authorize'); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getAccessTokenEndpoint() 58 | { 59 | return new Uri('https://accounts.spotify.com/api/token'); 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | protected function getAuthorizationMethod() 66 | { 67 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | protected function parseAccessTokenResponse($responseBody) 74 | { 75 | $data = json_decode($responseBody, true); 76 | 77 | if (null === $data || !is_array($data)) { 78 | throw new TokenResponseException('Unable to parse response.'); 79 | } elseif (isset($data['error'])) { 80 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 81 | } 82 | 83 | $token = new StdOAuth2Token(); 84 | $token->setAccessToken($data['access_token']); 85 | 86 | if (isset($data['expires_in'])) { 87 | $token->setLifetime($data['expires_in']); 88 | unset($data['expires_in']); 89 | } 90 | 91 | if (isset($data['refresh_token'])) { 92 | $token->setRefreshToken($data['refresh_token']); 93 | unset($data['refresh_token']); 94 | } 95 | 96 | unset($data['access_token']); 97 | 98 | $token->setExtraParams($data); 99 | 100 | return $token; 101 | } 102 | 103 | /** 104 | * {@inheritdoc} 105 | */ 106 | protected function getExtraOAuthHeaders() 107 | { 108 | return ['Authorization' => 'Basic ' . 109 | base64_encode($this->credentials->getConsumerId() . ':' . $this->credentials->getConsumerSecret()), ]; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Stripe.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://connect.stripe.com/'); 29 | } 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function getAuthorizationEndpoint() 36 | { 37 | return new Uri('https://connect.stripe.com/oauth/authorize'); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function getAccessTokenEndpoint() 44 | { 45 | return new Uri('https://connect.stripe.com/oauth/token'); 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | protected function getAuthorizationMethod() 52 | { 53 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | protected function parseAccessTokenResponse($responseBody) 60 | { 61 | $data = json_decode($responseBody, true); 62 | 63 | if (null === $data || !is_array($data)) { 64 | throw new TokenResponseException('Unable to parse response.'); 65 | } elseif (isset($data['error'])) { 66 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 67 | } 68 | 69 | $token = new StdOAuth2Token(); 70 | $token->setAccessToken($data['access_token']); 71 | 72 | unset($data['access_token']); 73 | 74 | $token->setExtraParams($data); 75 | 76 | return $token; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Ustream.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.ustream.tv/'); 34 | } 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAuthorizationEndpoint() 41 | { 42 | return new Uri('https://www.ustream.tv/oauth2/authorize'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function getAccessTokenEndpoint() 49 | { 50 | return new Uri('https://www.ustream.tv/oauth2/token'); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function getAuthorizationMethod() 57 | { 58 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | protected function parseAccessTokenResponse($responseBody) 65 | { 66 | $data = json_decode($responseBody, true); 67 | 68 | if (null === $data || !is_array($data)) { 69 | throw new TokenResponseException('Unable to parse response.'); 70 | } elseif (isset($data['error'])) { 71 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 72 | } 73 | 74 | $token = new StdOAuth2Token(); 75 | $token->setAccessToken($data['access_token']); 76 | $token->setLifeTime($data['expires_in']); 77 | 78 | if (isset($data['refresh_token'])) { 79 | $token->setRefreshToken($data['refresh_token']); 80 | unset($data['refresh_token']); 81 | } 82 | 83 | unset($data['access_token'], $data['expires_in']); 84 | 85 | $token->setExtraParams($data); 86 | 87 | return $token; 88 | } 89 | 90 | /** 91 | * {@inheritdoc} 92 | */ 93 | protected function getExtraOAuthHeaders() 94 | { 95 | return ['Authorization' => 'Basic ' . $this->credentials->getConsumerSecret()]; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Vkontakte.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.vk.com/method/'); 53 | } 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function getAuthorizationEndpoint() 60 | { 61 | return new Uri('https://oauth.vk.com/authorize'); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getAccessTokenEndpoint() 68 | { 69 | return new Uri('https://oauth.vk.com/access_token'); 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | protected function parseAccessTokenResponse($responseBody) 76 | { 77 | $data = json_decode($responseBody, true); 78 | 79 | if (null === $data || !is_array($data)) { 80 | throw new TokenResponseException('Unable to parse response.'); 81 | } elseif (isset($data['error'])) { 82 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 83 | } 84 | 85 | $token = new StdOAuth2Token(); 86 | $token->setAccessToken($data['access_token']); 87 | $token->setLifeTime($data['expires_in']); 88 | 89 | if (isset($data['refresh_token'])) { 90 | $token->setRefreshToken($data['refresh_token']); 91 | unset($data['refresh_token']); 92 | } 93 | 94 | unset($data['access_token'], $data['expires_in']); 95 | 96 | $token->setExtraParams($data); 97 | 98 | return $token; 99 | } 100 | 101 | /** 102 | * {@inheritdoc} 103 | */ 104 | protected function getAuthorizationMethod() 105 | { 106 | return static::AUTHORIZATION_METHOD_QUERY_STRING; 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | public function requestAccessToken($code, $state = null) 113 | { 114 | if (null !== $state) { 115 | $this->validateAuthorizationState($state); 116 | } 117 | 118 | $bodyParams = [ 119 | 'code' => $code, 120 | 'client_id' => $this->credentials->getConsumerId(), 121 | 'client_secret' => $this->credentials->getConsumerSecret(), 122 | 'redirect_uri' => $this->credentials->getCallbackUrl(), 123 | 'grant_type' => 'client_credentials', 124 | 125 | ]; 126 | 127 | $responseBody = $this->httpClient->retrieveResponse( 128 | $this->getAccessTokenEndpoint(), 129 | $bodyParams, 130 | $this->getExtraOAuthHeaders() 131 | ); 132 | 133 | $token = $this->parseAccessTokenResponse($responseBody); 134 | $this->storage->storeAccessToken($this->service(), $token); 135 | 136 | return $token; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Xing.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://api.xing.com/v1/'); 31 | } 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | public function getAuthorizationEndpoint() 38 | { 39 | return new Uri('https://api.xing.com/auth/oauth2/authorize'); 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function getAccessTokenEndpoint() 46 | { 47 | return new Uri('https://api.xing.com/auth/oauth2/token'); 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | protected function getAuthorizationMethod() 54 | { 55 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | protected function parseAccessTokenResponse($responseBody) 62 | { 63 | $data = json_decode($responseBody, true); 64 | 65 | if (null === $data || !is_array($data)) { 66 | throw new TokenResponseException('Unable to parse response.'); 67 | } elseif (isset($data['error'])) { 68 | throw new TokenResponseException(sprintf( 69 | 'Error in retrieving access token, error: "%s", description: "%s", uri: "%s".', 70 | $data['error'], 71 | $data['error_description'], 72 | $data['error_uri'] 73 | ) 74 | ); 75 | } 76 | 77 | $token = new StdOAuth2Token(); 78 | $token->setAccessToken($data['access_token']); 79 | $token->setLifeTime($data['expires_in']); 80 | $token->setRefreshToken($data['refresh_token']); 81 | 82 | unset($data['access_token'], $data['expires_in'], $data['refresh_token']); 83 | 84 | $token->setExtraParams($data); 85 | 86 | return $token; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Yahoo.php: -------------------------------------------------------------------------------- 1 | setAccessToken($data['access_token']); 50 | $token->setLifetime($data['expires_in']); 51 | 52 | if (isset($data['refresh_token'])) { 53 | $token->setRefreshToken($data['refresh_token']); 54 | unset($data['refresh_token']); 55 | } 56 | 57 | unset($data['access_token'], $data['expires_in']); 58 | 59 | $token->setExtraParams($data); 60 | 61 | return $token; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | protected function getExtraOAuthHeaders() 68 | { 69 | $encodedCredentials = base64_encode( 70 | $this->credentials->getConsumerId() . ':' . $this->credentials->getConsumerSecret() 71 | ); 72 | 73 | return ['Authorization' => 'Basic ' . $encodedCredentials]; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Yammer.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://www.yammer.com/api/v1/'); 26 | } 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function getAuthorizationEndpoint() 33 | { 34 | return new Uri('https://www.yammer.com/dialog/oauth'); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function getAccessTokenEndpoint() 41 | { 42 | return new Uri('https://www.yammer.com/oauth2/access_token.json'); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function getAuthorizationMethod() 49 | { 50 | return static::AUTHORIZATION_METHOD_HEADER_BEARER; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function parseAccessTokenResponse($responseBody) 57 | { 58 | $data = json_decode($responseBody, true); 59 | 60 | if (null === $data || !is_array($data)) { 61 | throw new TokenResponseException('Unable to parse response.'); 62 | } elseif (isset($data['error'])) { 63 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 64 | } 65 | 66 | $token = new StdOAuth2Token(); 67 | $token->setAccessToken($data['access_token']['token']); 68 | $token->setLifetime($data['access_token']['expires_at']); 69 | 70 | if (isset($data['refresh_token'])) { 71 | $token->setRefreshToken($data['refresh_token']); 72 | unset($data['refresh_token']); 73 | } 74 | 75 | unset($data['access_token'], $data['expires_in']); 76 | 77 | $token->setExtraParams($data); 78 | 79 | return $token; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Service/Yandex.php: -------------------------------------------------------------------------------- 1 | baseApiUri = new Uri('https://login.yandex.ru/'); 33 | } 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getAuthorizationEndpoint() 40 | { 41 | return new Uri('https://oauth.yandex.ru/authorize'); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getAccessTokenEndpoint() 48 | { 49 | return new Uri('https://oauth.yandex.ru/token'); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | protected function parseAccessTokenResponse($responseBody) 56 | { 57 | $data = json_decode($responseBody, true); 58 | if (null === $data || !is_array($data)) { 59 | throw new TokenResponseException('Unable to parse response.'); 60 | } elseif (isset($data['error'])) { 61 | throw new TokenResponseException('Error in retrieving token: "' . $data['error'] . '"'); 62 | } 63 | 64 | $token = new StdOAuth2Token(); 65 | $token->setAccessToken($data['access_token']); 66 | $token->setLifeTime($data['expires_in']); 67 | 68 | if (isset($data['refresh_token'])) { 69 | $token->setRefreshToken($data['refresh_token']); 70 | unset($data['refresh_token']); 71 | } 72 | 73 | unset($data['access_token']); 74 | unset($data['expires_in']); 75 | $token->setExtraParams($data); 76 | 77 | return $token; 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | protected function getAuthorizationMethod() 84 | { 85 | return static::AUTHORIZATION_METHOD_QUERY_STRING_V5; 86 | } 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/OAuth/OAuth2/Token/StdOAuth2Token.php: -------------------------------------------------------------------------------- 1 |