Compare commits

...

59 Commits

Author SHA1 Message Date
Vitaliy Filippov 40b0c7c3b7 Include more details in exceptions, add JSON Web Token implementation 2017-05-31 16:21:37 +03:00
Vitaliy Filippov 7b137a5d34 Add GenericProvider 2016-03-11 14:32:01 +03:00
Vitaliy Filippov b789b77c07 Simplify everything
* Remove useless wrapper code (IDPException, Entity\User, Grant\*, httpBuildQuery)
* Remove useless getUserUid(), getUserEmail(), getUserScreenName() methods that throw away remote-fetched data
* Do not depend on Guzzle, use just cURL instead
* Shorten namespace name and remove sub-namespaces
* Do not use Mockery in tests, use custom cURL mock instead (TESTS STILL PASS)
2015-04-19 00:29:09 +03:00
Ben Ramsey 7496e419e3 Merge pull request #257 from soundasleep/patch-1
Add link to third-party Coinbase OAuth2 provider
2015-04-09 07:42:57 -05:00
Jevon Wright a49c4c72e0 Add link to third-party Coinbase OAuth2 provider
Provided by https://github.com/openclerk/coinbase-oauth2
2015-04-09 18:40:52 +12:00
Ben Ramsey cd2e968b49 Add PHP 7 to the list of supported versions
[ci skip]
2015-04-02 11:09:47 -04:00
Ben Ramsey a190f87243 Merge pull request #255 from bajb/master
Send headers with auth getAccessToken requests
2015-04-02 10:59:33 -04:00
Brooke Bryan e73c7ac641 Send headers with auth getAccessToken requests 2015-04-02 15:12:37 +01:00
Phil Sturgeon 693025806a Merge pull request #244 from thephpleague/revert-242-migrate-eventbrite
Revert "Removing Eventbrite support and adding link in readme to new pac...
2015-03-21 13:18:11 -04:00
Phil Sturgeon 0a9d2e8efb Revert "Removing Eventbrite support and adding link in readme to new package" 2015-03-21 13:17:51 -04:00
Phil Sturgeon d4d37ccdb0 Merge pull request #242 from stevenmaguire/migrate-eventbrite
Removing Eventbrite support and adding link in readme to new package
2015-03-21 12:34:37 -04:00
Steven Maguire c6fa377634 removing eventbrite and adding link in readme 2015-03-21 11:27:33 -05:00
Ben Ramsey fe94c8e492 Merge pull request #241 from stevenmaguire/add-uber-link
Adding uber link to readme
2015-03-21 09:39:26 -05:00
Steven Maguire eda9653428 adding uber link to readme 2015-03-20 22:56:53 -05:00
Ben Ramsey 7c07e22055 Merge pull request #238 from neeckeloo/add-auth0-provider-link
Add link to Auth0 provider
2015-03-13 08:57:30 -05:00
Nicolas Eeckeloo 99056462e3 Add link to Auth0 provider 2015-03-13 13:15:45 +01:00
Ben Ramsey 2a95b9c58e Bumping master branch alias to 0.10.x-dev 2015-03-11 09:21:15 -05:00
Ben Ramsey 5a8a6ff1ba Updating badge icons 2015-03-11 09:21:15 -05:00
Ben Ramsey 395b345e3d Merge pull request #236 from vimishor/issue-230
[Fix] Invalid JSON in response will trigger fatal error
2015-03-11 08:40:57 -05:00
Alexandru Guzinschi cb300f7b6c [Fix] Invalid JSON in response trigger fatal error
If the server responded with an invalid JSON for `getAccessToken()`,
$result variable will be of type string instead of expected array.
This will result in a fatal error was being raised in AbstractProvider
when calling `prepareAccessTokenResult` method, which expects an
argument of type array.

Proposed solution is to set the variable `$result` to an empty array if
json_decode was not successful.

Doesn't make sense to throw an expection at this point, because response
will not have an access_token and an `InvalidArgumentException` will be
thrown latter when `$grant->handleResponse()` will be called.

Fix #230
2015-03-11 13:44:02 +02:00
Ben Ramsey a012fbbf0a Run Travis tests on PHP 7 and add linting to build 2015-03-10 16:56:02 -05:00
Ben Ramsey 76af6059fb Merge pull request #232 from shadowhand/provider-get-headers
Enhance ability to use client to make authenticated requests
2015-03-10 16:23:08 -05:00
Ben Ramsey 7faec8077f Merge branch 'geofflancaster-idpexception-empty-strings' 2015-03-10 16:03:13 -05:00
Ben Ramsey 847dbf5dfe Fixing broken test and renamed tests for clarity 2015-03-10 16:02:39 -05:00
Ben Ramsey 248f55c201 Merge branch 'geofflancaster-patch' into geofflancaster-idpexception-empty-strings
Conflicts:
	test/src/Exception/IDPExceptionTest.php
2015-03-10 16:01:48 -05:00
Woody Gilk f156dd905f update providers and tests 2015-03-10 15:50:53 -05:00
Woody Gilk 844df96de4 add ProviderInterface::getHeaders() for making authenticated requests 2015-03-10 15:50:53 -05:00
Geoff Lancaster da5e316c1b Merge pull request #1 from geofflancaster/master
Added test cases for the empty string edge cases
2015-03-10 14:33:40 -05:00
Geoff Lancaster 54e404f911 Added test cases for the empty string edge cases 2015-03-10 14:31:35 -05:00
Ben Ramsey 57ea7ac8f9 Merge pull request #229 from vimishor/issue-185
Added getResponseBody method in IDPException
2015-03-10 14:09:30 -05:00
Ben Ramsey 63329259ef Merge pull request #231 from shadowhand/patch-1
Add ZenPayroll to 3rd party provider list
2015-03-10 14:08:08 -05:00
Ben Ramsey 1289e8a084 Merge pull request #233 from shadowhand/patch-2
Stop using deprecated Travis option --dev
2015-03-10 14:02:04 -05:00
Woody Gilk c323d4a790 Stop using deprecated Travis option --dev
As per recent Travis builds:

> You are using the deprecated option "dev". Dev packages are installed by default now.
2015-03-01 11:58:12 -06:00
Woody Gilk 76e04fb3cc Add ZenPayroll to 3rd party provider list 2015-02-27 14:48:55 -06:00
Alexandru Guzinschi c0f8ebf920 Added getResponseBody method in IDPException
Problem:

Some providers are sending additional information when an error occurs,
which can't be accessed because property `$result` is protected.

Solution:

Data from this property can be accessed using `getResponseBody()` method.

Closes #185
2015-02-26 12:50:11 +02:00
Ben Ramsey a86dbd4e58 Merge pull request #227 from shadowhand/patch-1
Add Square to 3rd party provider links
2015-02-24 10:34:58 -06:00
Ben Ramsey 021023f642 Merge pull request #226 from shadowhand/overload-access-token-response
Add additional method for modifying token response
2015-02-24 10:34:43 -06:00
Ben Ramsey ee69b69923 Merge pull request #225 from shadowhand/clean-up-providers
Clean out custom provider code from AccessToken
2015-02-24 10:32:36 -06:00
Woody Gilk 5caeed7d0c Add Square to 3rd party provider links 2015-02-23 12:52:35 -06:00
Woody Gilk 4d2e8d5669 add AbstractProvider::prepareAccessTokenResult for additional token response prep 2015-02-23 12:23:37 -06:00
Woody Gilk 6373453f78 remove custom provider code from AccessToken 2015-02-23 12:15:25 -06:00
Woody Gilk 7446829c3b replace custom code in AccessToken with Vkontakte::$uidKey 2015-02-23 12:14:37 -06:00
Ben Ramsey e18c99c999 Merge pull request #221 from jasonvarga/patch-1
Add link to Dropbox provider
2015-02-12 13:50:54 -05:00
Jason Varga 3f8614ce86 Add link to Dropbox provider 2015-02-12 13:22:39 -05:00
Ben Ramsey bb2d4e4be7 Merge pull request #220 from jasonvarga/master
Allow approval_prompt to be set through options
2015-02-12 12:10:16 -05:00
Jason Varga 7ec9bf717f Remove Dropbox Provider
This will be moved to its own package
2015-02-12 11:49:01 -05:00
Ben Ramsey 09259e9728 Bump dev-master branch alias to 0.8.x-dev 2015-02-10 11:44:45 -06:00
Ben Ramsey 07b4641046 Merge pull request #218 from dolfelt/master
Get reliable body response on error.
2015-02-10 12:37:29 -05:00
Daniel Olfelt c88b91dcda Get reliable body response on error. 2015-02-05 15:52:06 -06:00
Ben Ramsey 2a728475d0 Merge pull request #210 from SammyK/update-facebook-scope
Upgrade Facebook provider to Graph v2.2
2015-02-03 18:06:22 -06:00
Ben Ramsey 362b2f9cab Merge pull request #207 from AnduAanei/Google_access_type
Add support for specifying the access_type parameter for Google OAuth
2015-02-03 09:35:01 -06:00
Jason Varga 993add9398 Some tests 2015-01-29 10:05:23 -05:00
Jason Varga 823774bf6e Dropbox provider 2015-01-29 09:08:48 -05:00
Jason Varga c918e21cdb Allow approval_prompt to be set through options 2015-01-29 09:07:56 -05:00
SammyK ebcb1b9abd Upgrade Facebook provider to Graph v2.2 2015-01-26 12:22:17 -06:00
Andu 3afc1f9a05 Add docblock for the access_type variable in the Google provider 2015-01-20 14:11:23 +00:00
Andu 3af0792195 Update Google provider tests 2015-01-20 12:35:46 +00:00
Andu 6e6f1d46db Add access_type parameter for Google authorization url 2015-01-20 12:31:49 +00:00
Geoff Lancaster a91f3788cb update idpexception to account for empty strings
Some providers (ex. Google) specify an error response object which is an empty string in cases where a 403/401 are returned. This will force the exception to check that the value isset and it is not an empty string which will help prevent the Unknown error case from occurring.
2015-01-16 15:19:14 -06:00
54 changed files with 1913 additions and 2248 deletions

View File

@ -4,17 +4,13 @@ php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
before_script:
- travis_retry composer self-update
- travis_retry composer require satooshi/php-coveralls:dev-master --no-update --dev
- travis_retry composer install --no-interaction --prefer-source --dev
script:
script:
- mkdir -p build/logs
- ./vendor/bin/parallel-lint src test
- ./vendor/bin/phpunit --coverage-text
- ./vendor/bin/phpcs src --standard=psr2
after_script:
- php vendor/bin/coveralls

112
README.md
View File

@ -1,9 +1,8 @@
# OAuth 2.0 Client
This is a STANDALONE SIMPLIFIED fork of https://github.com/thephpleague/oauth2-client/
[![Build Status](https://travis-ci.org/thephpleague/oauth2-client.png?branch=master)](https://travis-ci.org/thephpleague/oauth2-client)
[![Coverage Status](https://coveralls.io/repos/thephpleague/oauth2-client/badge.png)](https://coveralls.io/r/thephpleague/oauth2-client)
[![Total Downloads](https://poser.pugx.org/league/oauth2-client/downloads.png)](https://packagist.org/packages/league/oauth2-client)
[![Latest Stable Version](https://poser.pugx.org/league/oauth2-client/v/stable.png)](https://packagist.org/packages/league/oauth2-client)
cURL is used instead of Guzzle, some useless wrapper code is removed. Tests still pass.
# OAuth 2.0 Client
This package makes it stupidly simple to integrate your application with OAuth 2.0 identity providers.
@ -13,14 +12,6 @@ integration is an important feature of most web-apps these days. Many of these s
It will work with any OAuth 2.0 provider (be it an OAuth 2.0 Server for your own API or Facebook) and provides support
for popular systems out of the box. This package abstracts out some of the subtle but important differences between various providers, handles access tokens and refresh tokens, and allows you easy access to profile information on these other sites.
This package is compliant with [PSR-1][], [PSR-2][] and [PSR-4][]. If you notice compliance oversights, please send
a patch via pull request.
[PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
[PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
[PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
## Requirements
The following versions of PHP are supported.
@ -28,6 +19,7 @@ The following versions of PHP are supported.
* PHP 5.4
* PHP 5.5
* PHP 5.6
* PHP 7.0
* HHVM
## Usage
@ -35,45 +27,73 @@ The following versions of PHP are supported.
### Authorization Code Flow
```php
$provider = new League\OAuth2\Client\Provider\<ProviderName>([
$provider = new \OAuth2\<ProviderName>([
'clientId' => 'XXXXXXXX',
'clientSecret' => 'XXXXXXXX',
'redirectUri' => 'https://your-registered-redirect-uri/',
'scopes' => ['email', '...', '...'],
]);
if (!isset($_GET['code'])) {
// For example, with simplest GenericProvider and Keycloak
$provider = new \OAuth2\GenericProvider([
'clientId' => 'XXXXXXXX',
'clientSecret' => 'XXXXXXXX',
'urlAuthorize' => 'http://keycloak-server/auth/realms/example/protocol/openid-connect/auth',
'urlAccessToken' => 'http://keycloak-server/auth/realms/example/protocol/openid-connect/token',
'urlUserDetails' => 'http://keycloak-server/auth/realms/example/protocol/openid-connect/userinfo',
'scopes' => ['name', 'email'],
]);
$useJWT = false;
$jwksEndpointURL = '';
if (!isset($_GET['code']))
{
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->state;
header('Location: '.$authUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
}
elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state']))
{
// Check given state against previously stored one to mitigate CSRF attack
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
}
else
{
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// Optional: Now you have a token you can look up a users profile data
try {
try
{
if (!$useJWT)
{
// We got an access token, let's now get the user's details
$userDetails = $provider->getUserDetails($token);
}
else
{
// If your tokens are JWT (JSON Web Tokens) (Keycloak's ones are),
// you may decode and verify them instead of fetching user details from server
$keys = \OAuth2\JWT::extractKeys(json_decode(file_get_contents($jwksEndpointURL), true));
$userDetails = JWT::decode($token->accessToken, $keys);
// We got an access token, let's now get the user's details
$userDetails = $provider->getUserDetails($token);
// You may also just decode it without verifying
$userDetails = JWT::decode($token->accessToken, NULL);
}
// Use these details to create a new profile
printf('Hello %s!', $userDetails->firstName);
} catch (Exception $e) {
printf('Hello %s!', $userDetails['firstname']);
var_dump($userDetails);
}
catch (Exception $e)
{
// Failed to get user details
exit('Oh dear...');
}
@ -92,21 +112,20 @@ if (!isset($_GET['code'])) {
### Refreshing a Token
```php
$provider = new League\OAuth2\Client\Provider\<ProviderName>([
$provider = new \OAuth2\<ProviderName>([
'clientId' => 'XXXXXXXX',
'clientSecret' => 'XXXXXXXX',
'redirectUri' => 'https://your-registered-redirect-uri/',
]);
$grant = new \League\OAuth2\Client\Grant\RefreshToken();
$token = $provider->getAccessToken($grant, ['refresh_token' => $refreshToken]);
$token = $provider->getAccessToken('refresh_token', ['refresh_token' => $refreshToken]);
```
### Built-In Providers
This package currently has built-in support for:
- Basic GenericProvider suitable for any OAuth2 server
- Eventbrite
- Facebook
- Github
@ -126,28 +145,34 @@ below.
These providers allow integration with other providers not supported by `oauth2-client`. They may require an older version
so please help them out with a pull request if you notice this.
- [Auth0](https://github.com/RiskioFr/oauth2-auth0)
- [Battle.net](https://packagist.org/packages/depotwarehouse/oauth2-bnet)
- [Coinbase](https://github.com/openclerk/coinbase-oauth2)
- [Dropbox](https://github.com/pixelfear/oauth2-dropbox)
- [FreeAgent](https://github.com/CloudManaged/oauth2-freeagent)
- [Google Nest](https://github.com/JC5/nest-oauth2-provider)
- [Mail.ru](https://packagist.org/packages/aego/oauth2-mailru)
- [Meetup](https://github.com/howlowck/meetup-oauth2-provider)
- [Naver](https://packagist.org/packages/deminoth/oauth2-naver)
- [Odnoklassniki](https://packagist.org/packages/aego/oauth2-odnoklassniki)
- [Square](https://packagist.org/packages/wheniwork/oauth2-square)
- [Twitch.tv](https://github.com/tpavlek/oauth2-twitch)
- [Uber](https://github.com/stevenmaguire/oauth2-uber)
- [Vkontakte](https://packagist.org/packages/j4k/oauth2-vkontakte)
- [Yandex](https://packagist.org/packages/aego/oauth2-yandex)
- [ZenPayroll](https://packagist.org/packages/wheniwork/oauth2-zenpayroll)
### Implementing your own provider
If you are working with an oauth2 service not supported out-of-the-box or by an existing package, it is quite simple to
implement your own. Simply extend `League\OAuth2\Client\Provider\AbstractProvider` and implement the required abstract
implement your own. Simply extend `\OAuth2\AbstractProvider` and implement the required abstract
methods:
```php
abstract public function urlAuthorize();
abstract public function urlAccessToken();
abstract public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token);
abstract public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token);
abstract public function urlUserDetails(\OAuth2\AccessToken $token);
abstract public function userDetails($response, \OAuth2\AccessToken $token);
```
Each of these abstract methods contain a docblock defining their expectations and typical behaviour. Once you have
@ -166,18 +191,12 @@ provider you would add a property:
public $uidKey = 'accountId';
```
### Client Packages
Some developers use this library as a base for their own PHP API wrappers, and that seems like a really great idea. It might make it slightly tricky to integrate their provider with an existing generic "OAuth 2.0 All the Things" login system, but it does make working with them easier.
- [Sniply](https://github.com/younes0/sniply)
## Install
Via Composer
``` bash
$ composer require league/oauth2-client
$ composer require vitalif/oauth2-client
```
## Testing
@ -186,13 +205,9 @@ $ composer require league/oauth2-client
$ ./vendor/bin/phpunit
```
## Contributing
Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-client/blob/master/CONTRIBUTING.md) for details.
## Credits
- [Vitaliy Filippov](https://github.com/vitalif) - this simplified version
- [Alex Bilbie](https://github.com/alexbilbie)
- [Ben Corlett](https://github.com/bencorlett)
- [James Mills](https://github.com/jamesmills)
@ -200,7 +215,6 @@ Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-client/blob/mas
- [Tom Anderson](https://github.com/TomHAnderson)
- [All Contributors](https://github.com/thephpleague/oauth2-client/contributors)
## License
The MIT License (MIT). Please see [License File](https://github.com/thephpleague/oauth2-client/blob/master/LICENSE) for more information.
The MIT License (MIT). Please see [License File](https://github.com/vitalif/oauth2-client/blob/master/LICENSE) for more information.

View File

@ -1,15 +1,12 @@
{
"name": "league/oauth2-client",
"description": "OAuth 2.0 Client Library",
"name": "vitalif/oauth2-client",
"description": "OAuth 2.0 Client Library Simplified",
"license": "MIT",
"require": {
"php": ">=5.4.0",
"guzzle/guzzle": "~3.7"
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "~0.9",
"squizlabs/php_codesniffer": "~2.0"
"phpunit/phpunit": "~4.0"
},
"keywords": [
"oauth",
@ -31,17 +28,17 @@
],
"autoload": {
"psr-4": {
"League\\OAuth2\\Client\\": "src/"
"OAuth2\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"League\\OAuth2\\Client\\Test\\": "test/src/"
}
"OAuth2\\Test\\": "test/src/"
},
"files": ["test/CurlMock.php"]
},
"extra": {
"branch-alias": {
"dev-master": "0.7.x-dev"
}
}
}

308
src/AbstractProvider.php Normal file
View File

@ -0,0 +1,308 @@
<?php
namespace OAuth2;
interface ProviderInterface
{
public function urlAuthorize();
public function urlAccessToken();
public function urlUserDetails(AccessToken $token);
public function userDetails($response, AccessToken $token);
public function getScopes();
public function setScopes(array $scopes);
public function getAuthorizationUrl($options = []);
public function authorize($options = []);
public function getAccessToken($grant = 'authorization_code', $params = []);
public function getHeaders($token = null);
public function getUserDetails(AccessToken $token);
}
abstract class AbstractProvider implements ProviderInterface
{
public $clientId = '';
public $clientSecret = '';
public $redirectUri = '';
public $state;
public $name;
public $uidKey = 'uid';
public $scopes = [];
public $method = 'post';
public $scopeSeparator = ',';
public $responseType = 'json';
public $headers = [];
public $authorizationHeader;
protected $redirectHandler;
public function __construct($options = [])
{
foreach ($options as $option => $value)
{
if (property_exists($this, $option))
{
$this->{$option} = $value;
}
}
}
/**
* Get the URL that this provider uses to begin authorization.
*
* @return string
*/
abstract public function urlAuthorize();
/**
* Get the URL that this provider users to request an access token.
*
* @return string
*/
abstract public function urlAccessToken();
/**
* Get the URL that this provider uses to request user details.
*
* Since this URL is typically an authorized route, most providers will require you to pass the access_token as
* a parameter to the request. For example, the google url is:
*
* 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token='.$token
*
* @param AccessToken $token
* @return string
*/
abstract public function urlUserDetails(AccessToken $token);
/**
* Given an object response from the server, process the user details into a format expected by the user
* of the client.
*
* @param object $response
* @param AccessToken $token
* @return mixed
*/
abstract public function userDetails($response, AccessToken $token);
public function getScopes()
{
return $this->scopes;
}
public function setScopes(array $scopes)
{
$this->scopes = $scopes;
}
public function getAuthorizationUrl($options = [])
{
$this->state = isset($options['state']) ? $options['state'] : md5(uniqid(rand(), true));
$params = [
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUri,
'state' => $this->state,
'scope' => is_array($this->scopes) ? implode($this->scopeSeparator, $this->scopes) : $this->scopes,
'response_type' => isset($options['response_type']) ? $options['response_type'] : 'code',
'approval_prompt' => isset($options['approval_prompt']) ? $options['approval_prompt'] : 'auto',
];
return $this->urlAuthorize().'?'.http_build_query($params);
}
public function authorize($options = [])
{
$url = $this->getAuthorizationUrl($options);
if ($this->redirectHandler)
{
$handler = $this->redirectHandler;
return $handler($url);
}
header('Location: ' . $url);
exit;
}
/**
* @param string $grant: grant type, one of 'authorization_code' (default), 'client_credentials', 'refresh_token', 'password'
*/
public function getAccessToken($grant = 'authorization_code', $params = [])
{
if ($grant == 'password' && (empty($params['username']) || empty($params['password'])))
{
throw new \BadMethodCallException('Missing username or password');
}
elseif ($grant == 'authorization_code' && empty($params['code']))
{
throw new \BadMethodCallException('Missing authorization code');
}
elseif ($grant == 'refresh_token' && empty($params['refresh_token']))
{
throw new \BadMethodCallException('Missing refresh_token');
}
$requestParams = [
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'redirect_uri' => $this->redirectUri,
'grant_type' => $grant,
] + $params;
$curl = curl_init();
if (strtoupper($this->method) == 'POST')
{
curl_setopt_array($curl, [
CURLOPT_URL => ($url = $this->urlAccessToken()),
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => $this->getHeaders(),
CURLOPT_POSTFIELDS => http_build_query($requestParams),
CURLOPT_RETURNTRANSFER => true,
]);
}
else
{
// No providers included with this library use get but 3rd parties may
curl_setopt_array($curl, [
CURLOPT_URL => ($url = $this->urlAccessToken() . '?' . http_build_query($requestParams)),
CURLOPT_HTTPHEADER => $this->getHeaders(),
CURLOPT_RETURNTRANSFER => true,
]);
}
$response = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$errno = curl_errno($curl);
$error = curl_error($curl);
curl_close($curl);
switch ($this->responseType)
{
case 'json':
$result = json_decode($response, true);
if (JSON_ERROR_NONE !== json_last_error())
{
$result = [];
}
break;
case 'string':
$result = [];
parse_str($response, $result);
break;
}
if (isset($result['error']) && !empty($result['error']))
{
// OAuth 2.0 Draft 10 style
throw new \Exception($result['error']);
}
elseif (!$result)
{
// cURL?
throw new \Exception($url . ' returned: ' . ($code ? "HTTP $code, content: $response" : "cURL: $errno $error"));
}
$result = $this->prepareAccessTokenResult($result);
return new AccessToken($result);
}
/**
* Prepare the access token response for the grant. Custom mapping of
* expirations, etc should be done here.
*
* @param array $result
* @return array
*/
protected function prepareAccessTokenResult(array $result)
{
$this->setResultUid($result);
return $result;
}
/**
* Sets any result keys we've received matching our provider-defined uidKey to the key "uid".
*
* @param array $result
*/
protected function setResultUid(array &$result)
{
// If we're operating with the default uidKey there's nothing to do.
if ($this->uidKey === "uid")
{
return;
}
if (isset($result[$this->uidKey]))
{
// The AccessToken expects a "uid" to have the key "uid".
$result['uid'] = $result[$this->uidKey];
}
}
public function getUserDetails(AccessToken $token)
{
$response = $this->fetchUserDetails($token);
return $this->userDetails(json_decode($response), $token);
}
protected function fetchUserDetails(AccessToken $token)
{
$url = $this->urlUserDetails($token);
$headers = $this->getHeaders($token);
return $this->fetchProviderData($url, $headers);
}
protected function fetchProviderData($url, array $headers = [])
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
]);
$errno = curl_errno($curl);
$error = curl_error($curl);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status != 200)
{
throw new \Exception($url . ' returned: ' . ($status ? "HTTP $status, content: $response" : "cURL: $errno $error"));
}
return $response;
}
protected function getAuthorizationHeaders($token)
{
$headers = [];
if ($this->authorizationHeader)
{
$headers[] = 'Authorization: ' . $this->authorizationHeader . ' ' . $token;
}
return $headers;
}
public function getHeaders($token = null)
{
$headers = $this->headers;
if ($token)
{
$headers = array_merge($headers, $this->getAuthorizationHeaders($token));
}
return $headers;
}
public function setRedirectHandler(callable $handler)
{
$this->redirectHandler = $handler;
}
}

65
src/AccessToken.php Normal file
View File

@ -0,0 +1,65 @@
<?php
namespace OAuth2;
class AccessToken
{
public $accessToken;
public $expires;
public $refreshToken;
public $uid;
/**
* Sets the token, expiry, etc values.
*
* @param array $options token options
* @return void
*/
public function __construct(array $options = null)
{
if (!isset($options['access_token']))
{
throw new \InvalidArgumentException(
'Required option not passed: access_token in '.print_r($options, true)
);
}
$this->accessToken = $options['access_token'];
if (!empty($options['uid']))
{
$this->uid = $options['uid'];
}
if (!empty($options['refresh_token']))
{
$this->refreshToken = $options['refresh_token'];
}
// We need to know when the token expires. Show preference to
// 'expires_in' since it is defined in RFC6749 Section 5.1.
// Defer to 'expires' if it is provided instead.
if (!empty($options['expires_in']))
{
$this->expires = time() + ((int) $options['expires_in']);
}
elseif (!empty($options['expires']))
{
// Some providers supply the seconds until expiration rather than
// the exact timestamp. Take a best guess at which we received.
$expires = $options['expires'];
$expiresInFuture = $expires > time();
$this->expires = $expiresInFuture ? $expires : time() + ((int) $expires);
}
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->accessToken;
}
}

View File

@ -1,117 +0,0 @@
<?php
namespace League\OAuth2\Client\Entity;
class User
{
protected $uid;
protected $nickname;
protected $name;
protected $firstName;
protected $lastName;
protected $email;
protected $location;
protected $description;
protected $imageUrl;
protected $urls;
protected $gender;
protected $locale;
public function __get($name)
{
if (!property_exists($this, $name)) {
throw new \OutOfRangeException(sprintf(
'%s does not contain a property by the name of "%s"',
__CLASS__,
$name
));
}
return $this->{$name};
}
public function __set($property, $value)
{
if (!property_exists($this, $property)) {
throw new \OutOfRangeException(sprintf(
'%s does not contain a property by the name of "%s"',
__CLASS__,
$property
));
}
$this->$property = $value;
return $this;
}
public function __isset($name)
{
return (property_exists($this, $name));
}
public function getArrayCopy()
{
return [
'uid' => $this->uid,
'nickname' => $this->nickname,
'name' => $this->name,
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'email' => $this->email,
'location' => $this->location,
'description' => $this->description,
'imageUrl' => $this->imageUrl,
'urls' => $this->urls,
'gender' => $this->gender,
'locale' => $this->locale,
];
}
public function exchangeArray(array $data)
{
foreach ($data as $key => $value) {
$key = strtolower($key);
switch ($key) {
case 'uid':
$this->uid = $value;
break;
case 'nickname':
$this->nickname = $value;
break;
case 'name':
$this->name = $value;
break;
case 'firstname':
$this->firstName = $value;
break;
case 'lastname':
$this->lastName = $value;
break;
case 'email':
$this->email = $value;
break;
case 'location':
$this->location = $value;
break;
case 'description':
$this->description = $value;
break;
case 'imageurl':
$this->imageUrl = $value;
break;
case 'urls':
$this->urls = $value;
break;
case 'gender':
$this->gender = $value;
break;
case 'locale':
$this->locale = $value;
break;
}
}
return $this;
}
}

31
src/Eventbrite.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace OAuth2;
class Eventbrite extends AbstractProvider
{
public $authorizationHeader = 'Bearer';
public function urlAuthorize()
{
return 'https://www.eventbrite.com/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://www.eventbrite.com/oauth/token';
}
public function urlUserDetails(AccessToken $token)
{
return 'https://www.eventbrite.com/json/user_get';
}
public function userDetails($response, AccessToken $token)
{
return [
'uid' => $response->user->user_id,
'email' => $response->user->email,
];
}
}

View File

@ -1,59 +0,0 @@
<?php
namespace League\OAuth2\Client\Exception;
class IDPException extends \Exception
{
protected $result;
public function __construct($result)
{
$this->result = $result;
$code = isset($result['code']) ? $result['code'] : 0;
if (isset($result['error'])) {
// OAuth 2.0 Draft 10 style
$message = $result['error'];
} elseif (isset($result['message'])) {
// cURL style
$message = $result['message'];
} else {
$message = 'Unknown Error.';
}
parent::__construct($message, $code);
}
public function getType()
{
$result = 'Exception';
if (isset($this->result['error'])) {
$message = $this->result['error'];
if (is_string($message)) {
// OAuth 2.0 Draft 10 style
$result = $message;
}
}
return $result;
}
/**
* To make debugging easier.
*
* @return string The string representation of the error.
*/
public function __toString()
{
$str = $this->getType().': ';
if ($this->code != 0) {
$str .= $this->code.': ';
}
return $str.$this->message;
}
}

82
src/Facebook.php Normal file
View File

@ -0,0 +1,82 @@
<?php
namespace OAuth2;
class Facebook extends AbstractProvider
{
/**
* @const string The fallback Graph API version to use for requests.
*/
const DEFAULT_GRAPH_VERSION = 'v2.2';
/**
* @var string The Graph API version to use for requests.
*/
protected $graphApiVersion;
public $scopes = ['public_profile', 'email'];
public $responseType = 'string';
public function __construct($options)
{
parent::__construct($options);
$this->graphApiVersion = (isset($options['graphApiVersion']))
? $options['graphApiVersion']
: static::DEFAULT_GRAPH_VERSION;
}
public function urlAuthorize()
{
return 'https://www.facebook.com/'.$this->graphApiVersion.'/dialog/oauth';
}
public function urlAccessToken()
{
return 'https://graph.facebook.com/'.$this->graphApiVersion.'/oauth/access_token';
}
public function urlUserDetails(AccessToken $token)
{
$fields = implode(',', [
'id',
'name',
'first_name',
'last_name',
'email',
'hometown',
'bio',
'picture.type(large){url}',
'gender',
'locale',
'link',
]);
return 'https://graph.facebook.com/'.$this->graphApiVersion.'/me?fields='.$fields.'&access_token='.$token;
}
public function userDetails($response, AccessToken $token)
{
$email = (isset($response->email)) ? $response->email : null;
// The "hometown" field will only be returned if you ask for the `user_hometown` permission.
$location = (isset($response->hometown->name)) ? $response->hometown->name : null;
$description = (isset($response->bio)) ? $response->bio : null;
$imageUrl = (isset($response->picture->data->url)) ? $response->picture->data->url : null;
$gender = (isset($response->gender)) ? $response->gender : null;
$locale = (isset($response->locale)) ? $response->locale : null;
return [
'uid' => $response->id,
'name' => $response->name,
'firstname' => $response->first_name,
'lastname' => $response->last_name,
'email' => $email,
'location' => $location,
'description' => $description,
'image_url' => $imageUrl,
'gender' => $gender,
'locale' => $locale,
'urls' => [ 'Facebook' => $response->link ],
];
}
}

31
src/GenericProvider.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace OAuth2;
class GenericProvider extends AbstractProvider
{
public $scopes = ['basic'];
public $responseType = 'json';
public $urlAuthorize, $urlAccessToken, $urlUserDetails;
public $authorizationHeader = 'Bearer';
public function urlAuthorize()
{
return $this->urlAuthorize;
}
public function urlAccessToken()
{
return $this->urlAccessToken;
}
public function urlUserDetails(AccessToken $token)
{
return str_replace('$token', $token, $this->urlUserDetails);
}
public function userDetails($response, AccessToken $token)
{
return $response;
}
}

73
src/Github.php Normal file
View File

@ -0,0 +1,73 @@
<?php
namespace OAuth2;
class Github extends AbstractProvider
{
public $responseType = 'string';
public $authorizationHeader = 'token';
public $domain = 'https://github.com';
public $apiDomain = 'https://api.github.com';
public function urlAuthorize()
{
return $this->domain.'/login/oauth/authorize';
}
public function urlAccessToken()
{
return $this->domain.'/login/oauth/access_token';
}
public function urlUserDetails(AccessToken $token)
{
if ($this->domain === 'https://github.com')
{
return $this->apiDomain.'/user';
}
return $this->domain.'/api/v3/user';
}
public function urlUserEmails(AccessToken $token)
{
if ($this->domain === 'https://github.com')
{
return $this->apiDomain.'/user/emails';
}
return $this->domain.'/api/v3/user/emails';
}
public function userDetails($response, AccessToken $token)
{
$name = (isset($response->name)) ? $response->name : null;
$email = (isset($response->email)) ? $response->email : null;
return [
'uid' => $response->id,
'nickname' => $response->login,
'name' => $name,
'email' => $email,
'urls' => [
'GitHub' => $this->domain.'/'.$response->login,
],
];
}
public function getUserEmails(AccessToken $token)
{
$response = $this->fetchUserEmails($token);
return json_decode($response);
}
protected function fetchUserEmails(AccessToken $token)
{
$url = $this->urlUserEmails($token);
$headers = $this->getHeaders($token);
return $this->fetchProviderData($url, $headers);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
namespace OAuth2;
class Google extends AbstractProvider
{
@ -13,6 +11,8 @@ class Google extends AbstractProvider
'email',
];
public $authorizationHeader = 'OAuth';
/**
* @var string If set, this will be sent to google as the "hd" parameter.
* @link https://developers.google.com/accounts/docs/OAuth2Login#hd-param
@ -29,6 +29,22 @@ class Google extends AbstractProvider
return $this->hostedDomain;
}
/**
* @var string If set, this will be sent to google as the "access_type" parameter.
* @link https://developers.google.com/accounts/docs/OAuth2WebServer#offline
*/
public $accessType = '';
public function setAccessType($accessType)
{
$this->accessType = $accessType;
}
public function getAccessType()
{
return $this->accessType;
}
public function urlAuthorize()
{
return 'https://accounts.google.com/o/oauth2/auth';
@ -39,62 +55,45 @@ class Google extends AbstractProvider
return 'https://accounts.google.com/o/oauth2/token';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
public function urlUserDetails(AccessToken $token)
{
return
'https://www.googleapis.com/plus/v1/people/me?'.
'fields=id%2Cname(familyName%2CgivenName)%2CdisplayName%2C'.
'emails%2Fvalue%2Cimage%2Furl&alt=json&access_token='.$token;
'emails%2Fvalue%2Cimage%2Furl&alt=json';
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
public function userDetails($response, AccessToken $token)
{
$response = (array) $response;
$user = new User();
$imageUrl = (isset($response['image']) &&
$response['image']->url) ? $response['image']->url : null;
$email =
(isset($response['emails']) &&
count($response['emails']) &&
$response['emails'][0]->value)? $response['emails'][0]->value : null;
$email = (isset($response['emails']) && count($response['emails']) &&
$response['emails'][0]->value) ? $response['emails'][0]->value : null;
$user->exchangeArray([
return [
'uid' => $response['id'],
'name' => $response['displayName'],
'firstname' => $response['name']->givenName,
'lastName' => $response['name']->familyName,
'lastname' => $response['name']->familyName,
'email' => $email,
'imageUrl' => $imageUrl,
]);
return $user;
}
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->id;
}
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return ($response->emails &&
count($response->emails) &&
$response->emails[0]->value) ? $response->emails[0]->value : null;
}
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return [$response->name->givenName, $response->name->familyName];
'image_url' => $imageUrl,
];
}
public function getAuthorizationUrl($options = array())
{
$url = parent::getAuthorizationUrl($options);
if (!empty($this->hostedDomain)) {
$url .= '&' . $this->httpBuildQuery(['hd' => $this->hostedDomain]);
if (!empty($this->hostedDomain))
{
$url .= '&' . http_build_query(['hd' => $this->hostedDomain]);
}
if (!empty($this->accessType))
{
$url .= '&' . http_build_query(['access_type'=> $this->accessType]);
}
return $url;

View File

@ -1,27 +0,0 @@
<?php
namespace League\OAuth2\Client\Grant;
use League\OAuth2\Client\Token\AccessToken;
class AuthorizationCode implements GrantInterface
{
public function __toString()
{
return 'authorization_code';
}
public function prepRequestParams($defaultParams, $params)
{
if (! isset($params['code']) || empty($params['code'])) {
throw new \BadMethodCallException('Missing authorization code');
}
return array_merge($defaultParams, $params);
}
public function handleResponse($response = [])
{
return new AccessToken($response);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace League\OAuth2\Client\Grant;
use League\OAuth2\Client\Token\AccessToken;
class ClientCredentials implements GrantInterface
{
public function __toString()
{
return 'client_credentials';
}
public function prepRequestParams($defaultParams, $params)
{
$params['grant_type'] = 'client_credentials';
return array_merge($defaultParams, $params);
}
public function handleResponse($response = array())
{
return new AccessToken($response);
}
}

View File

@ -1,12 +0,0 @@
<?php
namespace League\OAuth2\Client\Grant;
interface GrantInterface
{
public function __toString();
public function handleResponse($response = []);
public function prepRequestParams($defaultParams, $params);
}

View File

@ -1,33 +0,0 @@
<?php
namespace League\OAuth2\Client\Grant;
use League\OAuth2\Client\Token\AccessToken;
class Password implements GrantInterface
{
public function __toString()
{
return 'password';
}
public function prepRequestParams($defaultParams, $params)
{
if (! isset($params['username']) || empty($params['username'])) {
throw new \BadMethodCallException('Missing username');
}
if (! isset($params['password']) || empty($params['password'])) {
throw new \BadMethodCallException('Missing password');
}
$params['grant_type'] = 'password';
return array_merge($defaultParams, $params);
}
public function handleResponse($response = array())
{
return new AccessToken($response);
}
}

View File

@ -1,29 +0,0 @@
<?php
namespace League\OAuth2\Client\Grant;
use League\OAuth2\Client\Token\AccessToken as AccessToken;
class RefreshToken implements GrantInterface
{
public function __toString()
{
return 'refresh_token';
}
public function prepRequestParams($defaultParams, $params)
{
if (! isset($params['refresh_token']) || empty($params['refresh_token'])) {
throw new \BadMethodCallException('Missing refresh_token');
}
$params['grant_type'] = 'refresh_token';
return array_merge($defaultParams, $params);
}
public function handleResponse($response = [])
{
return new AccessToken($response);
}
}

36
src/Instagram.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace OAuth2;
class Instagram extends AbstractProvider
{
public $scopes = ['basic'];
public $responseType = 'json';
public function urlAuthorize()
{
return 'https://api.instagram.com/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://api.instagram.com/oauth/access_token';
}
public function urlUserDetails(AccessToken $token)
{
return 'https://api.instagram.com/v1/users/self?access_token='.$token;
}
public function userDetails($response, AccessToken $token)
{
$description = (isset($response->data->bio)) ? $response->data->bio : null;
return [
'uid' => $response->data->id,
'nickname' => $response->data->username,
'name' => $response->data->full_name,
'description' => $description,
'image_url' => $response->data->profile_picture,
];
}
}

476
src/JWT.php Normal file
View File

@ -0,0 +1,476 @@
<?php
namespace OAuth2;
/**
* JSON Web Token implementation, based on this spec:
* http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
*
* PHP version 5
*
* @category Authentication
* @package Authentication_JWT
* @author Neuman Vong <neuman@twilio.com>
* @author Anant Narayanan <anant@php.net>
* @author Vitaliy Filippov <vitalif@mail.ru>
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
* @link https://github.com/firebase/php-jwt (forked from here)
*/
class JWT
{
/**
* When checking nbf, iat or expiration times,
* we want to provide some extra leeway time to
* account for clock skew.
*/
public static $leeway = 0;
/**
* Allow the current timestamp to be specified.
* Useful for fixing a value within unit testing.
*
* Will default to PHP time() value if null.
*/
public static $timestamp = null;
public static $supported_algs = array(
'HS256' => array('hash_hmac', 'SHA256'),
'HS512' => array('hash_hmac', 'SHA512'),
'HS384' => array('hash_hmac', 'SHA384'),
'RS256' => array('openssl', 'SHA256'),
);
/**
* Extract keys from JWKS response structure
* { keys: [ { kid, kty, alg, use, n, e }, ... ] }
*
* For example, from Keycloak's "certs" endpoint URL:
* http://your-keycloak-server.com/auth/realms/your-realm/protocol/openid-connect/certs
*/
public static function extractKeys(array $jwks)
{
if (!isset($jwks['keys']) || !is_array($jwks['keys']))
{
return NULL;
}
$keys = [];
foreach ($jwks['keys'] as $key)
{
if (!isset($key['kid']) || !isset($key['kty']))
{
continue;
}
if ($key['kty'] == 'RSA')
{
if (!isset($key['n']) || !isset($key['e']))
{
continue;
}
$keys[$key['kid']] = JWT_RSAPubKey::modexp2openssl($key['n'], $key['e']);
}
elseif ($key['kty'] == 'oct')
{
if (!isset($key['k']))
{
continue;
}
$keys[$key['kid']] = $key['k'];
}
}
return $keys;
}
/**
* Decodes a JWT string into a PHP object.
*
* @param string $jwt The JWT
* @param string|array|null $key The key, or map of keys.
* If the algorithm used is asymmetric, this is the public key
* If empty, no verification is performed
*
* @return object The JWT's payload as a PHP object
*
* @throws UnexpectedValueException Provided JWT was invalid
* @throws JWT_SignatureInvalidException Provided JWT was invalid because the signature verification failed
* @throws JWT_BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
* @throws JWT_BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
* @throws JWT_ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
*
* @uses jsonDecode
* @uses urlsafeB64Decode
*/
public static function decode($jwt, $key)
{
$timestamp = is_null(static::$timestamp) ? time() : static::$timestamp;
$tks = explode('.', $jwt);
if (count($tks) != 3)
{
throw new \UnexpectedValueException('Wrong number of segments');
}
list($headb64, $bodyb64, $cryptob64) = $tks;
if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64))))
{
throw new \UnexpectedValueException('Invalid header encoding');
}
if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64)))
{
throw new \UnexpectedValueException('Invalid claims encoding');
}
$sig = static::urlsafeB64Decode($cryptob64);
if ($key)
{
if (empty($header['alg']))
{
throw new \UnexpectedValueException('Empty algorithm');
}
if (empty(static::$supported_algs[$header['alg']]))
{
throw new \UnexpectedValueException('Algorithm not supported');
}
if (is_array($key) || $key instanceof \ArrayAccess)
{
if (isset($header['kid']))
{
$key = $key[$header['kid']];
}
else
{
throw new \UnexpectedValueException('"kid" empty, unable to lookup correct key');
}
}
// Check the signature
if (!static::verify("$headb64.$bodyb64", $sig, $key, $header['alg']))
{
throw new JWT_SignatureInvalidException('Signature verification failed');
}
}
// Check if the nbf if it is defined. This is the time that the
// token can actually be used. If it's not yet that time, abort.
if (isset($payload['nbf']) && $payload['nbf'] > ($timestamp + static::$leeway))
{
throw new JWT_BeforeValidException(
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload['nbf'])
);
}
// Check that this token has been created before 'now'. This prevents
// using tokens that have been created for later use (and haven't
// correctly used the nbf claim).
if (isset($payload['iat']) && $payload['iat'] > ($timestamp + static::$leeway))
{
throw new JWT_BeforeValidException(
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload['iat'])
);
}
// Check if this token has expired.
if (isset($payload['exp']) && ($timestamp - static::$leeway) >= $payload['exp'])
{
throw new JWT_ExpiredException('Expired token');
}
return $payload;
}
/**
* Converts and signs a PHP object or array into a JWT string.
*
* @param object|array $payload PHP object or array
* @param string $key The secret key.
* If the algorithm used is asymmetric, this is the private key
* @param string $alg The signing algorithm.
* Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
* @param mixed $keyId
* @param array $head An array with header elements to attach
*
* @return string A signed JWT
*
* @uses jsonEncode
* @uses urlsafeB64Encode
*/
public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
{
$header = array('typ' => 'JWT', 'alg' => $alg);
if ($keyId !== null)
{
$header['kid'] = $keyId;
}
if (isset($head) && is_array($head))
{
$header = array_merge($head, $header);
}
$segments = array();
$segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
$segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
$signing_input = implode('.', $segments);
$signature = static::sign($signing_input, $key, $alg);
$segments[] = static::urlsafeB64Encode($signature);
return implode('.', $segments);
}
/**
* Sign a string with a given key and algorithm.
*
* @param string $msg The message to sign
* @param string|resource $key The secret key
* @param string $alg The signing algorithm.
* Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
*
* @return string An encrypted message
*
* @throws DomainException Unsupported algorithm was specified
*/
public static function sign($msg, $key, $alg = 'HS256')
{
if (empty(static::$supported_algs[$alg]))
{
throw new \DomainException('Algorithm not supported');
}
list($function, $algorithm) = static::$supported_algs[$alg];
if ($function == 'hash_hmac')
{
return hash_hmac($algorithm, $msg, $key, true);
}
elseif ($function == 'openssl')
{
$signature = '';
$success = openssl_sign($msg, $signature, $key, $algorithm);
if (!$success)
throw new \DomainException("OpenSSL unable to sign data");
else
return $signature;
}
}
/**
* Verify a signature with the message, key and method. Not all methods
* are symmetric, so we must have a separate verify and sign method.
*
* @param string $msg The original message (header and body)
* @param string $signature The original signature
* @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key
* @param string $alg The algorithm
*
* @return bool
*
* @throws DomainException Invalid Algorithm or OpenSSL failure
*/
private static function verify($msg, $signature, $key, $alg)
{
if (empty(static::$supported_algs[$alg]))
{
throw new \DomainException('Algorithm not supported');
}
list($function, $algorithm) = static::$supported_algs[$alg];
if ($function == 'openssl')
{
$success = openssl_verify($msg, $signature, $key, $algorithm);
if (!$success)
throw new \DomainException("OpenSSL unable to verify data: " . openssl_error_string());
else
return $signature;
}
else /* if ($function == 'hash_hmac') */
{
$hash = hash_hmac($algorithm, $msg, $key, true);
if (function_exists('hash_equals'))
{
return hash_equals($signature, $hash);
}
$len = min(strlen($signature), strlen($hash));
$status = 0;
for ($i = 0; $i < $len; $i++)
$status |= (ord($signature[$i]) ^ ord($hash[$i]));
$status |= (strlen($signature) ^ strlen($hash));
return ($status === 0);
}
}
/**
* Decode a JSON string into a PHP object.
*
* @param string $input JSON string
*
* @return object Object representation of JSON string
*
* @throws DomainException Provided string was invalid JSON
*/
public static function jsonDecode($input)
{
if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4))
{
/** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
* to specify that large ints (like Steam Transaction IDs) should be treated as
* strings, rather than the PHP default behaviour of converting them to floats.
*/
$obj = json_decode($input, true, 512, JSON_BIGINT_AS_STRING);
}
else
{
/** Not all servers will support that, however, so for older versions we must
* manually detect large ints in the JSON string and quote them (thus converting
*them to strings) before decoding, hence the preg_replace() call.
*/
$max_int_length = strlen((string) PHP_INT_MAX) - 1;
$json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
$obj = json_decode($json_without_bigints, true);
}
if (function_exists('json_last_error') && $errno = json_last_error())
{
static::handleJsonError($errno);
}
elseif ($obj === null && $input !== 'null')
{
throw new \DomainException('Null result with non-null input');
}
return $obj;
}
/**
* Encode a PHP object into a JSON string.
*
* @param object|array $input A PHP object or array
*
* @return string JSON representation of the PHP object or array
*
* @throws DomainException Provided object could not be encoded to valid JSON
*/
public static function jsonEncode($input)
{
$json = json_encode($input);
if (function_exists('json_last_error') && $errno = json_last_error())
{
static::handleJsonError($errno);
}
elseif ($json === 'null' && $input !== null)
{
throw new \DomainException('Null result with non-null input');
}
return $json;
}
/**
* Decode a string with URL-safe Base64.
*
* @param string $input A Base64 encoded string
*
* @return string A decoded string
*/
public static function urlsafeB64Decode($input)
{
$remainder = strlen($input) % 4;
if ($remainder)
{
$padlen = 4 - $remainder;
$input .= str_repeat('=', $padlen);
}
return base64_decode(strtr($input, '-_', '+/'));
}
/**
* Encode a string with URL-safe Base64.
*
* @param string $input The string you want encoded
*
* @return string The base64 encode of what you passed in
*/
public static function urlsafeB64Encode($input)
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
/**
* Helper method to create a JSON error.
*
* @param int $errno An error number from json_last_error()
*
* @return void
*/
private static function handleJsonError($errno)
{
$messages = array(
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON'
);
throw new \DomainException(
isset($messages[$errno])
? $messages[$errno]
: 'Unknown JSON error: ' . $errno
);
}
}
class JWT_BeforeValidException extends \UnexpectedValueException
{
}
class JWT_ExpiredException extends \UnexpectedValueException
{
}
class JWT_SignatureInvalidException extends \UnexpectedValueException
{
}
class JWT_RSAPubKey
{
protected static function asn1length($len)
{
if ($len < 0x80)
return chr($len);
elseif ($len < 0x100)
return chr(0x81) . chr($len);
elseif ($len < 0x10000)
return chr(0x82) . chr(0xFF & ($len >> 8)) . chr(0xFF & $len);
elseif ($len < 0x1000000)
return chr(0x83) . chr(0xFF & ($len >> 16)) . chr(0xFF & ($len >> 8)) . chr(0xFF & $len);
else
return chr(0x84) . chr(0xFF & ($len >> 24)) . chr(0xFF & ($len >> 16)) . chr(0xFF & ($len >> 8)) . chr(0xFF & $len);
}
protected static function asn1int($int)
{
$int = (ord($int{0}) > 0x7f ? "\x00" : "") . $int;
return "\x02" . self::asn1length(strlen($int)) . $int;
}
protected static function asn1seq($elem1, $elem2)
{
return "\x30" . self::asn1length(strlen($elem1) + strlen($elem2)) . $elem1 . $elem2;
}
protected static function asn1bitstring($elem)
{
$elem = "\x00" . $elem;
return "\x03" . self::asn1length(strlen($elem)) . $elem;
}
/**
* Convert modulus + exponent ('n', 'e' fields from JWK) to OpenSSL RSA public key format
*/
public static function modexp2openssl($mod, $exp)
{
$rsaid = hex2bin('300D06092A864886F70D0101010500');
$exp = base64_decode(str_replace([ '-', '_' ], [ '+', '/' ], $exp), true);
$mod = base64_decode(str_replace([ '-', '_' ], [ '+', '/' ], $mod), true);
if (!$mod || !$exp)
return '';
$pk = self::asn1seq($rsaid, self::asn1bitstring(self::asn1seq(self::asn1int($mod), self::asn1int($exp))));
$pk = base64_encode($pk);
$pk = preg_replace('/(.{64})/', "\$1\n", $pk);
$pk = "-----BEGIN PUBLIC KEY-----\n$pk\n-----END PUBLIC KEY-----\n";
return $pk;
}
}

View File

@ -1,14 +1,12 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
use League\OAuth2\Client\Token\AccessToken;
namespace OAuth2;
class LinkedIn extends AbstractProvider
{
public $scopes = ['r_basicprofile r_emailaddress r_contactinfo'];
public $responseType = 'json';
public $authorizationHeader = 'Bearer';
public $fields = [
'id', 'email-address', 'first-name', 'last-name', 'headline',
'location', 'industry', 'picture-url', 'public-profile-url',
@ -26,20 +24,18 @@ class LinkedIn extends AbstractProvider
public function urlUserDetails(AccessToken $token)
{
return 'https://api.linkedin.com/v1/people/~:('.implode(",", $this->fields)
.')?format=json&oauth2_access_token='.$token;
$fields = implode(',', $this->fields);
return 'https://api.linkedin.com/v1/people/~:(' . $fields . ')?format=json';
}
public function userDetails($response, AccessToken $token)
{
$user = new User();
$email = (isset($response->emailAddress)) ? $response->emailAddress : null;
$location = (isset($response->location->name)) ? $response->location->name : null;
$description = (isset($response->headline)) ? $response->headline : null;
$pictureUrl = (isset($response->pictureUrl)) ? $response->pictureUrl : null;
$user->exchangeArray([
return [
'uid' => $response->id,
'name' => $response->firstName.' '.$response->lastName,
'firstname' => $response->firstName,
@ -47,27 +43,8 @@ class LinkedIn extends AbstractProvider
'email' => $email,
'location' => $location,
'description' => $description,
'imageurl' => $pictureUrl,
'image_url' => $pictureUrl,
'urls' => $response->publicProfileUrl,
]);
return $user;
}
public function userUid($response, AccessToken $token)
{
return $response->id;
}
public function userEmail($response, AccessToken $token)
{
return isset($response->emailAddress) && $response->emailAddress
? $response->emailAddress
: null;
}
public function userScreenName($response, AccessToken $token)
{
return [$response->firstName, $response->lastName];
];
}
}

51
src/Microsoft.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace OAuth2;
class Microsoft extends AbstractProvider
{
public $scopes = ['wl.basic', 'wl.emails'];
public $responseType = 'json';
public function urlAuthorize()
{
return 'https://login.live.com/oauth20_authorize.srf';
}
public function urlAccessToken()
{
return 'https://login.live.com/oauth20_token.srf';
}
public function urlUserDetails(AccessToken $token)
{
return 'https://apis.live.net/v5.0/me?access_token='.$token;
}
public function userDetails($response, AccessToken $token)
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://apis.live.net/v5.0/'.$response->id.'/picture',
CURLOPT_FOLLOWLOCATION => 0,
CURLOPT_HEADER => 1,
CURLOPT_RETURNTRANSFER => 1,
]);
$redir = curl_exec($curl);
curl_close($curl);
preg_match('/^Location: (.*)$/im', $redir, $m);
$imageUrl = $m ? $m[1] : false;
$email = (isset($response->emails->preferred)) ? $response->emails->preferred : null;
return [
'uid' => $response->id,
'name' => $response->name,
'firstname' => $response->first_name,
'lastname' => $response->last_name,
'email' => $email,
'image_url' => $imageUrl,
'urls' => $response->link.'/cid-'.$response->id,
];
}
}

View File

@ -1,344 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use Closure;
use Guzzle\Http\Exception\BadResponseException;
use Guzzle\Service\Client as GuzzleClient;
use League\OAuth2\Client\Exception\IDPException as IDPException;
use League\OAuth2\Client\Grant\GrantInterface;
use League\OAuth2\Client\Token\AccessToken as AccessToken;
abstract class AbstractProvider implements ProviderInterface
{
public $clientId = '';
public $clientSecret = '';
public $redirectUri = '';
public $state;
public $name;
public $uidKey = 'uid';
public $scopes = [];
public $method = 'post';
public $scopeSeparator = ',';
public $responseType = 'json';
public $headers = null;
/**
* @var GuzzleClient
*/
protected $httpClient;
protected $redirectHandler;
/**
* @var int This represents: PHP_QUERY_RFC1738, which is the default value for php 5.4
* and the default encryption type for the http_build_query setup
*/
protected $httpBuildEncType = 1;
public function __construct($options = [])
{
foreach ($options as $option => $value) {
if (property_exists($this, $option)) {
$this->{$option} = $value;
}
}
$this->setHttpClient(new GuzzleClient());
}
public function setHttpClient(GuzzleClient $client)
{
$this->httpClient = $client;
return $this;
}
public function getHttpClient()
{
$client = clone $this->httpClient;
return $client;
}
/**
* Get the URL that this provider uses to begin authorization.
*
* @return string
*/
abstract public function urlAuthorize();
/**
* Get the URL that this provider users to request an access token.
*
* @return string
*/
abstract public function urlAccessToken();
/**
* Get the URL that this provider uses to request user details.
*
* Since this URL is typically an authorized route, most providers will require you to pass the access_token as
* a parameter to the request. For example, the google url is:
*
* 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token='.$token
*
* @param AccessToken $token
* @return string
*/
abstract public function urlUserDetails(AccessToken $token);
/**
* Given an object response from the server, process the user details into a format expected by the user
* of the client.
*
* @param object $response
* @param AccessToken $token
* @return mixed
*/
abstract public function userDetails($response, AccessToken $token);
public function getScopes()
{
return $this->scopes;
}
public function setScopes(array $scopes)
{
$this->scopes = $scopes;
}
public function getAuthorizationUrl($options = [])
{
$this->state = isset($options['state']) ? $options['state'] : md5(uniqid(rand(), true));
$params = [
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUri,
'state' => $this->state,
'scope' => is_array($this->scopes) ? implode($this->scopeSeparator, $this->scopes) : $this->scopes,
'response_type' => isset($options['response_type']) ? $options['response_type'] : 'code',
'approval_prompt' => 'auto',
];
return $this->urlAuthorize().'?'.$this->httpBuildQuery($params, '', '&');
}
// @codeCoverageIgnoreStart
public function authorize($options = [])
{
$url = $this->getAuthorizationUrl($options);
if ($this->redirectHandler) {
$handler = $this->redirectHandler;
return $handler($url);
}
// @codeCoverageIgnoreStart
header('Location: ' . $url);
exit;
// @codeCoverageIgnoreEnd
}
public function getAccessToken($grant = 'authorization_code', $params = [])
{
if (is_string($grant)) {
// PascalCase the grant. E.g: 'authorization_code' becomes 'AuthorizationCode'
$className = str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $grant)));
$grant = 'League\\OAuth2\\Client\\Grant\\'.$className;
if (! class_exists($grant)) {
throw new \InvalidArgumentException('Unknown grant "'.$grant.'"');
}
$grant = new $grant();
} elseif (! $grant instanceof GrantInterface) {
$message = get_class($grant).' is not an instance of League\OAuth2\Client\Grant\GrantInterface';
throw new \InvalidArgumentException($message);
}
$defaultParams = [
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'redirect_uri' => $this->redirectUri,
'grant_type' => $grant,
];
$requestParams = $grant->prepRequestParams($defaultParams, $params);
try {
switch (strtoupper($this->method)) {
case 'GET':
// @codeCoverageIgnoreStart
// No providers included with this library use get but 3rd parties may
$client = $this->getHttpClient();
$client->setBaseUrl($this->urlAccessToken() . '?' . $this->httpBuildQuery($requestParams, '', '&'));
$request = $client->get(null, null, $requestParams)->send();
$response = $request->getBody();
break;
// @codeCoverageIgnoreEnd
case 'POST':
$client = $this->getHttpClient();
$client->setBaseUrl($this->urlAccessToken());
$request = $client->post(null, null, $requestParams)->send();
$response = $request->getBody();
break;
// @codeCoverageIgnoreStart
default:
throw new \InvalidArgumentException('Neither GET nor POST is specified for request');
// @codeCoverageIgnoreEnd
}
} catch (BadResponseException $e) {
// @codeCoverageIgnoreStart
$raw_response = explode("\n", $e->getResponse());
$response = end($raw_response);
// @codeCoverageIgnoreEnd
}
switch ($this->responseType) {
case 'json':
$result = json_decode($response, true);
break;
case 'string':
parse_str($response, $result);
break;
}
if (isset($result['error']) && ! empty($result['error'])) {
// @codeCoverageIgnoreStart
throw new IDPException($result);
// @codeCoverageIgnoreEnd
}
$this->setResultUid($result);
return $grant->handleResponse($result);
}
/**
* Sets any result keys we've received matching our provider-defined uidKey to the key "uid".
*
* @param array $result
*/
protected function setResultUid(array &$result)
{
// If we're operating with the default uidKey there's nothing to do.
if ($this->uidKey === "uid") {
return;
}
if (isset($result[$this->uidKey])) {
// The AccessToken expects a "uid" to have the key "uid".
$result['uid'] = $result[$this->uidKey];
}
}
public function getUserDetails(AccessToken $token)
{
$response = $this->fetchUserDetails($token);
return $this->userDetails(json_decode($response), $token);
}
public function getUserUid(AccessToken $token)
{
$response = $this->fetchUserDetails($token, true);
return $this->userUid(json_decode($response), $token);
}
public function getUserEmail(AccessToken $token)
{
$response = $this->fetchUserDetails($token, true);
return $this->userEmail(json_decode($response), $token);
}
public function getUserScreenName(AccessToken $token)
{
$response = $this->fetchUserDetails($token, true);
return $this->userScreenName(json_decode($response), $token);
}
public function userUid($response, AccessToken $token)
{
return isset($response->id) && $response->id ? $response->id : null;
}
public function userEmail($response, AccessToken $token)
{
return isset($response->email) && $response->email ? $response->email : null;
}
public function userScreenName($response, AccessToken $token)
{
return isset($response->name) && $response->name ? $response->name : null;
}
/**
* Build HTTP the HTTP query, handling PHP version control options
*
* @param array $params
* @param integer $numeric_prefix
* @param string $arg_separator
* @param null|integer $enc_type
*
* @return string
* @codeCoverageIgnoreStart
*/
protected function httpBuildQuery($params, $numeric_prefix = 0, $arg_separator = '&', $enc_type = null)
{
if (version_compare(PHP_VERSION, '5.4.0', '>=') && !defined('HHVM_VERSION')) {
if ($enc_type === null) {
$enc_type = $this->httpBuildEncType;
}
$url = http_build_query($params, $numeric_prefix, $arg_separator, $enc_type);
} else {
$url = http_build_query($params, $numeric_prefix, $arg_separator);
}
return $url;
}
protected function fetchUserDetails(AccessToken $token)
{
$url = $this->urlUserDetails($token);
return $this->fetchProviderData($url);
}
protected function fetchProviderData($url)
{
try {
$client = $this->getHttpClient();
$client->setBaseUrl($url);
if ($this->headers) {
$client->setDefaultOption('headers', $this->headers);
}
$request = $client->get()->send();
$response = $request->getBody();
} catch (BadResponseException $e) {
// @codeCoverageIgnoreStart
$raw_response = explode("\n", $e->getResponse());
throw new IDPException(end($raw_response));
// @codeCoverageIgnoreEnd
}
return $response;
}
public function setRedirectHandler(Closure $handler)
{
$this->redirectHandler = $handler;
}
}

View File

@ -1,57 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
class Eventbrite extends AbstractProvider
{
public function __construct($options)
{
parent::__construct($options);
$this->headers = [
'Authorization' => 'Bearer',
];
}
public function urlAuthorize()
{
return 'https://www.eventbrite.com/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://www.eventbrite.com/oauth/token';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
{
return 'https://www.eventbrite.com/json/user_get?access_token='.$token;
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
$user = new User();
$user->exchangeArray([
'uid' => $response->user->user_id,
'email' => $response->user->email,
]);
return $user;
}
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->user->user_id;
}
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return isset($response->user->email) && $response->user->email ? $response->user->email : null;
}
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->user->user_id;
}
}

View File

@ -1,73 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
class Facebook extends AbstractProvider
{
public $scopes = ['offline_access', 'email', 'read_stream'];
public $responseType = 'string';
public function urlAuthorize()
{
return 'https://www.facebook.com/dialog/oauth';
}
public function urlAccessToken()
{
return 'https://graph.facebook.com/oauth/access_token';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
{
return 'https://graph.facebook.com/me?access_token='.$token;
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
$client = $this->getHttpClient();
$client->setBaseUrl('https://graph.facebook.com/me/picture?type=normal&access_token='.$token->accessToken);
$request = $client->get()->send();
$info = $request->getInfo();
$imageUrl = $info['url'];
$user = new User();
$username = (isset($response->username)) ? $response->username : null;
$email = (isset($response->email)) ? $response->email : null;
$location = (isset($response->hometown->name)) ? $response->hometown->name : null;
$description = (isset($response->bio)) ? $response->bio : null;
$imageUrl = ($imageUrl) ?: null;
$user->exchangeArray([
'uid' => $response->id,
'nickname' => $username,
'name' => $response->name,
'firstname' => $response->first_name,
'lastname' => $response->last_name,
'email' => $email,
'location' => $location,
'description' => $description,
'imageurl' => $imageUrl,
'urls' => [ 'Facebook' => $response->link ],
]);
return $user;
}
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->id;
}
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return isset($response->email) && $response->email ? $response->email : null;
}
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return [$response->first_name, $response->last_name];
}
}

View File

@ -1,94 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
class Github extends AbstractProvider
{
public $responseType = 'string';
public $domain = 'https://github.com';
public $apiDomain = 'https://api.github.com';
public function urlAuthorize()
{
return $this->domain.'/login/oauth/authorize';
}
public function urlAccessToken()
{
return $this->domain.'/login/oauth/access_token';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
{
if ($this->domain === 'https://github.com') {
return $this->apiDomain.'/user?access_token='.$token;
}
return $this->domain.'/api/v3/user?access_token='.$token;
}
public function urlUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
{
if ($this->domain === 'https://github.com') {
return $this->apiDomain.'/user/emails?access_token='.$token;
}
return $this->domain.'/api/v3/user/emails?access_token='.$token;
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
$user = new User();
$name = (isset($response->name)) ? $response->name : null;
$email = (isset($response->email)) ? $response->email : null;
$user->exchangeArray([
'uid' => $response->id,
'nickname' => $response->login,
'name' => $name,
'email' => $email,
'urls' => [
'GitHub' => $this->domain.'/'.$response->login,
],
]);
return $user;
}
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->id;
}
public function getUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
{
$response = $this->fetchUserEmails($token);
return $this->userEmails(json_decode($response), $token);
}
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return isset($response->email) && $response->email ? $response->email : null;
}
public function userEmails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response;
}
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->name;
}
protected function fetchUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
{
$url = $this->urlUserEmails($token);
return $this->fetchProviderData($url);
}
}

View File

@ -1,58 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
class Instagram extends AbstractProvider
{
public $scopes = ['basic'];
public $responseType = 'json';
public function urlAuthorize()
{
return 'https://api.instagram.com/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://api.instagram.com/oauth/access_token';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
{
return 'https://api.instagram.com/v1/users/self?access_token='.$token;
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
$user = new User();
$description = (isset($response->data->bio)) ? $response->data->bio : null;
$user->exchangeArray([
'uid' => $response->data->id,
'nickname' => $response->data->username,
'name' => $response->data->full_name,
'description' => $description,
'imageUrl' => $response->data->profile_picture,
]);
return $user;
}
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->data->id;
}
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return;
}
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return $response->data->full_name;
}
}

View File

@ -1,69 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
use League\OAuth2\Client\Token\AccessToken;
class Microsoft extends AbstractProvider
{
public $scopes = ['wl.basic', 'wl.emails'];
public $responseType = 'json';
public function urlAuthorize()
{
return 'https://login.live.com/oauth20_authorize.srf';
}
public function urlAccessToken()
{
return 'https://login.live.com/oauth20_token.srf';
}
public function urlUserDetails(AccessToken $token)
{
return 'https://apis.live.net/v5.0/me?access_token='.$token;
}
public function userDetails($response, AccessToken $token)
{
$client = $this->getHttpClient();
$client->setBaseUrl('https://apis.live.net/v5.0/'.$response->id.'/picture');
$request = $client->get()->send();
$info = $request->getInfo();
$imageUrl = $info['url'];
$user = new User();
$email = (isset($response->emails->preferred)) ? $response->emails->preferred : null;
$user->exchangeArray([
'uid' => $response->id,
'name' => $response->name,
'firstname' => $response->first_name,
'lastname' => $response->last_name,
'email' => $email,
'imageurl' => $imageUrl,
'urls' => $response->link.'/cid-'.$response->id,
]);
return $user;
}
public function userUid($response, AccessToken $token)
{
return $response->id;
}
public function userEmail($response, AccessToken $token)
{
return isset($response->emails->preferred) && $response->emails->preferred
? $response->emails->preferred
: null;
}
public function userScreenName($response, AccessToken $token)
{
return [$response->first_name, $response->last_name];
}
}

View File

@ -1,34 +0,0 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Token\AccessToken as AccessToken;
interface ProviderInterface
{
public function urlAuthorize();
public function urlAccessToken();
public function urlUserDetails(AccessToken $token);
public function userDetails($response, AccessToken $token);
public function getScopes();
public function setScopes(array $scopes);
public function getAuthorizationUrl($options = []);
public function authorize($options = []);
public function getAccessToken($grant = 'authorization_code', $params = []);
public function getUserDetails(AccessToken $token);
public function getUserUid(AccessToken $token);
public function getUserEmail(AccessToken $token);
public function getUserScreenName(AccessToken $token);
}

View File

@ -1,84 +0,0 @@
<?php
namespace League\OAuth2\Client\Token;
use InvalidArgumentException;
class AccessToken
{
/**
* @var string accessToken
*/
public $accessToken;
/**
* @var int expires
*/
public $expires;
/**
* @var string refreshToken
*/
public $refreshToken;
/**
* @var string uid
*/
public $uid;
/**
* Sets the token, expiry, etc values.
*
* @param array $options token options
* @return void
*/
public function __construct(array $options = null)
{
if (! isset($options['access_token'])) {
throw new \InvalidArgumentException(
'Required option not passed: access_token'.PHP_EOL
.print_r($options, true)
);
}
$this->accessToken = $options['access_token'];
// Some providers (not many) give the uid here, so lets take it
isset($options['uid']) and $this->uid = $options['uid'];
// Vkontakte uses user_id instead of uid
isset($options['user_id']) and $this->uid = $options['user_id'];
// Mailru uses x_mailru_vid instead of uid
isset($options['x_mailru_vid']) and $this->uid = $options['x_mailru_vid'];
//Battle.net uses accountId instead of uid
isset($options['accountId']) and $this->uid = $options['accountId'];
// We need to know when the token expires. Show preference to
// 'expires_in' since it is defined in RFC6749 Section 5.1.
// Defer to 'expires' if it is provided instead.
if (!empty($options['expires_in'])) {
$this->expires = time() + ((int) $options['expires_in']);
} elseif (!empty($options['expires'])) {
// Some providers supply the seconds until expiration rather than
// the exact timestamp. Take a best guess at which we received.
$expires = $options['expires'];
$expiresInFuture = $expires > time();
$this->expires = $expiresInFuture ? $expires : time() + ((int) $expires);
}
// Grab a refresh token so we can update access tokens when they expires
isset($options['refresh_token']) and $this->refreshToken = $options['refresh_token'];
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->accessToken;
}
}

View File

@ -1,14 +1,10 @@
<?php
namespace League\OAuth2\Client\Provider;
use League\OAuth2\Client\Entity\User;
use League\OAuth2\Client\Token\AccessToken;
namespace OAuth2;
class Vkontakte extends AbstractProvider
{
public $scopes = [];
public $responseType = 'json';
public $uidKey = 'user_id';
public function urlAuthorize()
{
@ -22,7 +18,8 @@ class Vkontakte extends AbstractProvider
public function urlUserDetails(AccessToken $token)
{
$fields = ['nickname',
$fields = [
'nickname',
'screen_name',
'sex',
'bdate',
@ -46,7 +43,8 @@ class Vkontakte extends AbstractProvider
'can_post',
'universities',
'schools',
'verified', ];
'verified'
];
return "https://api.vk.com/method/users.get?user_id={$token->uid}&fields="
.implode(",", $fields)."&access_token={$token}";
@ -56,13 +54,11 @@ class Vkontakte extends AbstractProvider
{
$response = $response->response[0];
$user = new User();
$email = (isset($response->email)) ? $response->email : null;
$location = (isset($response->country)) ? $response->country : null;
$description = (isset($response->status)) ? $response->status : null;
$user->exchangeArray([
return [
'uid' => $response->uid,
'nickname' => $response->nickname,
'name' => $response->screen_name,
@ -71,30 +67,7 @@ class Vkontakte extends AbstractProvider
'email' => $email,
'location' => $location,
'description' => $description,
'imageUrl' => $response->photo_200_orig,
]);
return $user;
}
public function userUid($response, AccessToken $token)
{
$response = $response->response[0];
return $response->uid;
}
public function userEmail($response, AccessToken $token)
{
$response = $response->response[0];
return isset($response->email) && $response->email ? $response->email : null;
}
public function userScreenName($response, AccessToken $token)
{
$response = $response->response[0];
return [$response->first_name, $response->last_name];
'image_url' => $response->photo_200_orig,
];
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace LeagueTests\OAuth2\Client;
namespace OAuth2;
error_reporting(E_ALL | E_STRICT);
chdir(__DIR__);

63
test/CurlMock.php Normal file
View File

@ -0,0 +1,63 @@
<?php
namespace OAuth2;
class CurlMock
{
static $pending = [];
static function addPendingResponse($exec_ok, $status_line, $headers, $body)
{
self::$pending[] = [ $exec_ok, $status_line, $headers, $body ];
}
var $options = [];
var $response = [];
function __construct($response)
{
$this->response = $response;
}
}
function curl_init()
{
if (!CurlMock::$pending)
{
return false;
}
return new CurlMock(array_shift(CurlMock::$pending));
}
function curl_setopt_array($curl, $array)
{
$curl->options = $array + $curl->options;
}
function curl_exec($curl)
{
if (!$curl->response[0])
{
return false;
}
if (!empty($curl->options[CURLOPT_RETURNTRANSFER]))
{
if (!empty($curl->options[CURLOPT_HEADER]))
{
return trim($curl->response[2])."\n\n".$curl->response[3];
}
return $curl->response[3];
}
return true;
}
function curl_close($curl)
{
}
function curl_getinfo($curl, $opt)
{
if ($opt == CURLINFO_HTTP_CODE)
{
return intval($curl->response[1]);
}
return false;
}

View File

@ -0,0 +1,119 @@
<?php
namespace OAuth2\Test;
class AbstractProviderTest extends \PHPUnit_Framework_TestCase
{
/**
* @var AbstractProvider
*/
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function testAuthorizationUrlStateParam()
{
$this->assertContains('state=XXX', $this->provider->getAuthorizationUrl([
'state' => 'XXX'
]));
}
/**
* Tests https://github.com/thephpleague/oauth2-client/issues/134
*/
public function testConstructorSetsProperties()
{
$options = [
'clientId' => '1234',
'clientSecret' => '4567',
'redirectUri' => 'http://example.org/redirect',
'state' => 'foo',
'name' => 'bar',
'uidKey' => 'mynewuid',
'scopes' => ['a', 'b', 'c'],
'method' => 'get',
'scopeSeparator' => ';',
'responseType' => 'csv',
'headers' => ['Foo' => 'Bar'],
'authorizationHeader' => 'Bearer',
];
$mockProvider = new MockProvider($options);
foreach ($options as $key => $value)
{
$this->assertEquals($value, $mockProvider->{$key});
}
}
public function testSetRedirectHandler()
{
$this->testFunction = false;
$callback = function ($url) {
$this->testFunction = $url;
};
$this->provider->setRedirectHandler($callback);
$this->provider->authorize('http://test.url/');
$this->assertNotFalse($this->testFunction);
}
public function getHeadersTest()
{
$provider = $this->getMockForAbstractClass(
'\OAuth2\AbstractProvider',
[
[
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]
]
);
/**
* @var $provider AbstractProvider
*/
$this->assertEquals([], $provider->getHeaders());
$this->assertEquals([], $provider->getHeaders('mock_token'));
$provider->authorizationHeader = 'Bearer';
$this->assertEquals(['Authorization: Bearer abc'], $provider->getHeaders('abc'));
$token = new \OAuth2\AccessToken(['access_token' => 'xyz', 'expires_in' => 3600]);
$this->assertEquals(['Authorization: Bearer xyz'], $provider->getHeaders($token));
}
}
class MockProvider extends \OAuth2\AbstractProvider
{
public function urlAuthorize()
{
return '';
}
public function urlAccessToken()
{
return '';
}
public function urlUserDetails(\OAuth2\AccessToken $token)
{
return '';
}
public function userDetails($response, \OAuth2\AccessToken $token)
{
return '';
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Token;
namespace OAuth2\Test;
class AccessTokenTest extends \PHPUnit_Framework_TestCase
{
@ -9,13 +9,13 @@ class AccessTokenTest extends \PHPUnit_Framework_TestCase
*/
public function testInvalidRefreshToken()
{
new \League\OAuth2\Client\Token\AccessToken(['invalid_access_token' => 'none']);
new \OAuth2\AccessToken(['invalid_access_token' => 'none']);
}
public function testExpiresInCorrection()
{
$options = array('access_token' => 'access_token', 'expires_in' => 100);
$token = new \League\OAuth2\Client\Token\AccessToken($options);
$token = new \OAuth2\AccessToken($options);
$this->assertNotNull($token->expires);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Grant;
use Mockery as m;
namespace OAuth2\Test;
class AuthorizationCodeTest extends \PHPUnit_Framework_TestCase
{
@ -10,25 +8,13 @@ class AuthorizationCodeTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google([
$this->provider = new \OAuth2\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testGetAccessToken()
{
$grant = new \League\OAuth2\Client\Grant\AuthorizationCode();
$this->assertEquals('authorization_code', (string) $grant);
}
/**
* @expectedException BadMethodCallException
*/

View File

@ -0,0 +1,25 @@
<?php
namespace OAuth2\Test;
class ClientCredentialsTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Google(array(
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
));
}
public function testGetAccessToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('client_credentials');
$this->assertInstanceOf('\OAuth2\AccessToken', $token);
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Entity;
use League\OAuth2\Client\Entity\User;
class UserTest extends \PHPUnit_Framework_TestCase
{
private $user;
private $userArray;
public function setUp()
{
$this->user = new User();
$this->userArray = [
'uid' => 'mock_uid',
'nickname' => 'mock_nickname',
'name' => 'mock_name',
'firstName' => 'mock_firstName',
'lastName' => 'mock_lastName',
'email' => 'mock_email',
'location' => 'mock_location',
'description' => 'mock_description',
'imageUrl' => 'mock_imageUrl',
'urls' => 'mock_urls',
'gender' => 'mock_gender',
'locale' => 'mock_locale',
];
}
public function testExchangeArrayGetArrayCopy()
{
$this->user->exchangeArray($this->userArray);
$this->assertEquals($this->userArray, $this->user->getArrayCopy());
}
public function testMagicMethos()
{
$this->user->exchangeArray($this->userArray);
$this->user->name = 'mock_change_test';
$this->assertTrue(isset($this->user->name));
$this->assertEquals('mock_change_test', $this->user->name);
}
/**
* @expectedException \OutOfRangeException
*/
public function testInvalidMagicSet()
{
$this->user->invalidProp = 'mock';
}
/**
* @expectedException \OutOfRangeException
*/
public function testInvalidMagicGet()
{
$this->user->invalidProp;
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
namespace OAuth2\Test;
class EventbriteTest extends \PHPUnit_Framework_TestCase
{
@ -10,19 +8,13 @@ class EventbriteTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Eventbrite([
$this->provider = new \OAuth2\Eventbrite([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
@ -48,13 +40,7 @@ class EventbriteTest extends \PHPUnit_Framework_TestCase
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
@ -72,25 +58,13 @@ class EventbriteTest extends \PHPUnit_Framework_TestCase
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"user": {"user_id": 12345, "email": "mock_email"}}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$client->shouldReceive('setDefaultOption')->times(4);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"user": {"user_id": 12345, "email": "mock_email"}}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals(12345, $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $user->email);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_email', $user['email']);
}
}

View File

@ -1,44 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Exception;
use League\OAuth2\Client\Exception\IDPException;
class IDPExceptionTest extends \PHPUnit_Framework_TestCase
{
public function testGetTypeErrorMessage()
{
$exception = new IDPException(array('error' => 'message'));
$this->assertEquals('message', $exception->getType());
}
public function testGetTypeMessage()
{
$exception = new IDPException(array('message' => 'message'));
$this->assertEquals('Exception', $exception->getType());
}
public function testGetTypeEmpty()
{
$exception = new IDPException([]);
$this->assertEquals('Exception', $exception->getType());
}
public function testAsString()
{
$exception = new IDPException(array('error' => 'message'));
$this->assertEquals('message: message', (string)$exception);
}
public function testAsStringWithCode()
{
$exception = new IDPException(array('error' => 'message', 'code' => 404));
$this->assertEquals('message: 404: message', (string)$exception);
}
}

105
test/src/FacebookTest.php Normal file
View File

@ -0,0 +1,105 @@
<?php
namespace OAuth2\Test;
class FacebookTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Facebook([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$graphVersion = \OAuth2\Facebook::DEFAULT_GRAPH_VERSION;
$this->assertEquals('/'.$graphVersion.'/oauth/access_token', $uri['path']);
}
public function testGraphApiVersionCanBeCustomized()
{
$graphVersion = 'v13.37';
$provider = new \OAuth2\Facebook([
'graphApiVersion' => $graphVersion,
]);
$fooToken = new \OAuth2\AccessToken(['access_token' => 'foo_token']);
$urlAuthorize = $provider->urlAuthorize();
$urlAccessToken = $provider->urlAccessToken();
$urlUserDetails = parse_url($provider->urlUserDetails($fooToken), PHP_URL_PATH);
$this->assertEquals('https://www.facebook.com/'.$graphVersion.'/dialog/oauth', $urlAuthorize);
$this->assertEquals('https://graph.facebook.com/'.$graphVersion.'/oauth/access_token', $urlAccessToken);
$this->assertEquals('/'.$graphVersion.'/me', $urlUserDetails);
}
public function testGraphApiVersionWillFallbackToDefault()
{
$graphVersion = \OAuth2\Facebook::DEFAULT_GRAPH_VERSION;
$fooToken = new \OAuth2\AccessToken(['access_token' => 'foo_token']);
$urlAuthorize = $this->provider->urlAuthorize();
$urlAccessToken = $this->provider->urlAccessToken();
$urlUserDetails = parse_url($this->provider->urlUserDetails($fooToken), PHP_URL_PATH);
$this->assertEquals('https://www.facebook.com/'.$graphVersion.'/dialog/oauth', $urlAuthorize);
$this->assertEquals('https://graph.facebook.com/'.$graphVersion.'/oauth/access_token', $urlAccessToken);
$this->assertEquals('/'.$graphVersion.'/me', $urlUserDetails);
}
public function testGetAccessToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
public function testScopes()
{
$this->assertEquals(['public_profile', 'email'], $this->provider->getScopes());
}
public function testUserData()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"id": 12345, "name": "mock_name", "username": "mock_username", "first_name": "mock_first_name", "last_name": "mock_last_name", "email": "mock_email", "Location": "mock_home", "bio": "mock_description", "link": "mock_facebook_url", "picture": {"data":{"url":"mock_image_url"}}}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_first_name', $user['firstname']);
$this->assertEquals('mock_last_name', $user['lastname']);
$this->assertEquals('mock_email', $user['email']);
$this->assertEquals('mock_image_url', $user['image_url']);
}
}

141
test/src/GithubTest.php Normal file
View File

@ -0,0 +1,141 @@
<?php
namespace OAuth2\Test;
class GithubTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Github([
'clientId' => 'mock',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$this->assertEquals('/login/oauth/access_token', $uri['path']);
}
public function testGetAccessToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
/**
* @ticket 230
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Required option not passed: access_token
*/
public function testGetAccessTokenWithInvalidJson()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'invalid');
$this->provider->responseType = 'json';
$this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
}
public function testGetAccessTokenSetResultUid()
{
$this->provider->uidKey = 'otherKey';
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('{1234}', $token->uid);
}
public function testScopes()
{
$this->provider->setScopes(['user', 'repo']);
$this->assertEquals(['user', 'repo'], $this->provider->getScopes());
}
public function testUserData()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"id": 12345, "login": "mock_login", "name": "mock_name", "email": "mock_email"}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_name', $user['name']);
$this->assertEquals('mock_email', $user['email']);
}
public function testGithubDomainUrls()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals($this->provider->domain.'/login/oauth/authorize', $this->provider->urlAuthorize());
$this->assertEquals($this->provider->domain.'/login/oauth/access_token', $this->provider->urlAccessToken());
$this->assertEquals($this->provider->apiDomain.'/user', $this->provider->urlUserDetails($token));
$this->assertEquals($this->provider->apiDomain.'/user/emails', $this->provider->urlUserEmails($token));
}
public function testGithubEnterpriseDomainUrls()
{
$this->provider->domain = 'https://github.company.com';
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals($this->provider->domain.'/login/oauth/authorize', $this->provider->urlAuthorize());
$this->assertEquals($this->provider->domain.'/login/oauth/access_token', $this->provider->urlAccessToken());
$this->assertEquals($this->provider->domain.'/api/v3/user', $this->provider->urlUserDetails($token));
$this->assertEquals($this->provider->domain.'/api/v3/user/emails', $this->provider->urlUserEmails($token));
}
public function testUserEmails()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '[{"email":"mock_email_1","primary":false,"verified":true},{"email":"mock_email_2","primary":false,"verified":true},{"email":"mock_email_3","primary":true,"verified":true}]');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$emails = $this->provider->getUserEmails($token);
$this->assertInternalType('array', $emails);
$this->assertCount(3, $emails);
$this->assertEquals('mock_email_3', $emails[2]->email);
$this->assertTrue($emails[2]->primary);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
namespace OAuth2\Test;
class GoogleTest extends \PHPUnit_Framework_TestCase
{
@ -10,20 +8,15 @@ class GoogleTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google([
$this->provider = new \OAuth2\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
'hostedDomain' => 'mock_domain',
'accessType' => 'mock_access_type'
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
@ -37,6 +30,7 @@ class GoogleTest extends \PHPUnit_Framework_TestCase
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertArrayHasKey('hd', $query);
$this->assertArrayHasKey('access_type', $query);
$this->assertNotNull($this->provider->state);
}
@ -50,18 +44,10 @@ class GoogleTest extends \PHPUnit_Framework_TestCase
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
# print_r($token);die();
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
@ -76,25 +62,16 @@ class GoogleTest extends \PHPUnit_Framework_TestCase
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"emails": [{"value": "mock_email"}],"id": "12345","displayName": "mock_name","name": {"familyName": "mock_last_name","givenName": "mock_first_name"},"image": {"url": "mock_image_url"}}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"emails": [{"value": "mock_email"}],"id": "12345","displayName": "mock_name","name": {"familyName": "mock_last_name","givenName": "mock_first_name"},"image": {"url": "mock_image_url"}}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals(['mock_first_name', 'mock_last_name'], $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals('mock_email', $user->email);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_first_name', $user['firstname']);
$this->assertEquals('mock_last_name', $user['lastname']);
$this->assertEquals('mock_email', $user['email']);
}
public function testGetHostedDomain()
@ -107,4 +84,15 @@ class GoogleTest extends \PHPUnit_Framework_TestCase
$this->provider->setHostedDomain('changed_domain');
$this->assertEquals('changed_domain', $this->provider->hostedDomain);
}
public function testGetAccessType()
{
$this->assertEquals('mock_access_type', $this->provider->getAccessType());
}
public function testSetAccessType()
{
$this->provider->setAccessType('changed_access_type');
$this->assertEquals('changed_access_type', $this->provider->accessType);
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Grant;
use Mockery as m;
class ClientCredentialsTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google(array(
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
));
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('client_credentials');
$this->assertInstanceOf('League\OAuth2\Client\Token\AccessToken', $token);
$grant = new \League\OAuth2\Client\Grant\ClientCredentials();
$this->assertEquals('client_credentials', (string) $grant);
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Grant;
use Mockery as m;
class RefreshTokenTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(2)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(2);
$client->shouldReceive('post->send')->times(2)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertInstanceOf('League\OAuth2\Client\Token\AccessToken', $token);
$grant = new \League\OAuth2\Client\Grant\RefreshToken();
$this->assertEquals('refresh_token', (string) $grant);
$newToken = $this->provider->getAccessToken($grant, ['refresh_token' => $token->refreshToken]);
$this->assertInstanceOf('League\OAuth2\Client\Token\AccessToken', $newToken);
}
/**
* @expectedException BadMethodCallException
*/
public function testInvalidRefreshToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$grant = new \League\OAuth2\Client\Grant\RefreshToken();
$refreshToken = $this->provider->getAccessToken($grant, ['invalid_refresh_token' => $token->refreshToken]);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
namespace OAuth2\Test;
class InstagramTest extends \PHPUnit_Framework_TestCase
{
@ -10,19 +8,13 @@ class InstagramTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Instagram([
$this->provider = new \OAuth2\Instagram([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
@ -48,18 +40,10 @@ class InstagramTest extends \PHPUnit_Framework_TestCase
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
# print_r($token);die();
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
@ -74,24 +58,14 @@ class InstagramTest extends \PHPUnit_Framework_TestCase
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"data": {"id": "12345", "username": "mock_username", "full_name": "mock_full_name", "bio": "mock_bio", "profile_picture": "mock_profile_picture"}}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"data": {"id": "12345", "username": "mock_username", "full_name": "mock_full_name", "bio": "mock_bio", "profile_picture": "mock_profile_picture"}}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals('mock_full_name', $this->provider->getUserScreenName($token));
$this->assertEquals(null, $this->provider->getUserEmail($token));
$this->assertEquals(null, $user->email);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_full_name', $user['name']);
$this->assertEquals(true, !isset($user['email']));
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
namespace OAuth2\Test;
class LinkedInTest extends \PHPUnit_Framework_TestCase
{
@ -10,19 +8,13 @@ class LinkedInTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\LinkedIn([
$this->provider = new \OAuth2\LinkedIn([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
@ -48,18 +40,10 @@ class LinkedInTest extends \PHPUnit_Framework_TestCase
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
# print_r($token);die();
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
@ -74,24 +58,15 @@ class LinkedInTest extends \PHPUnit_Framework_TestCase
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"id": 12345, "firstName": "mock_first_name", "lastName": "mock_last_name", "emailAddress": "mock_email", "location": { "name": "mock_location" }, "headline": "mock_headline", "pictureUrl": "mock_picture_url", "publicProfileUrl": "mock_profile_url"}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"id": 12345, "firstName": "mock_first_name", "lastName": "mock_last_name", "emailAddress": "mock_email", "location": { "name": "mock_location" }, "headline": "mock_headline", "pictureUrl": "mock_picture_url", "publicProfileUrl": "mock_profile_url"}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals(['mock_first_name', 'mock_last_name'], $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals('mock_email', $user->email);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_first_name', $user['firstname']);
$this->assertEquals('mock_last_name', $user['lastname']);
$this->assertEquals('mock_email', $user['email']);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
namespace OAuth2\Test;
class MicrosoftTest extends \PHPUnit_Framework_TestCase
{
@ -10,19 +8,13 @@ class MicrosoftTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Microsoft([
$this->provider = new \OAuth2\Microsoft([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
@ -56,18 +48,10 @@ class MicrosoftTest extends \PHPUnit_Framework_TestCase
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
# print_r($token);die();
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
@ -82,27 +66,17 @@ class MicrosoftTest extends \PHPUnit_Framework_TestCase
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"id": 12345, "name": "mock_name", "first_name": "mock_first_name", "last_name": "mock_last_name", "emails": {"preferred": "mock_email"}, "link": "mock_link"}');
$getResponse->shouldReceive('getInfo')->andReturn(array('url' => 'mock_image_url'));
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(6);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(5)->andReturn($getResponse);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"id": 12345, "name": "mock_name", "first_name": "mock_first_name", "last_name": "mock_last_name", "emails": {"preferred": "mock_email"}, "link": "mock_link"}');
\OAuth2\CurlMock::addPendingResponse(true, "302 Found", 'Location: mock_image_url', '');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals(['mock_first_name', 'mock_last_name'], $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals('mock_email', $user->email);
$this->assertEquals('mock_image_url', $user->imageUrl);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_first_name', $user['firstname']);
$this->assertEquals('mock_last_name', $user['lastname']);
$this->assertEquals('mock_email', $user['email']);
$this->assertEquals('mock_image_url', $user['image_url']);
}
}

View File

@ -1,8 +1,6 @@
<?php
namespace League\OAuth2\Client\Test\Grant;
use Mockery as m;
namespace OAuth2\Test;
class PasswordTest extends \PHPUnit_Framework_TestCase
{
@ -10,34 +8,19 @@ class PasswordTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google(array(
$this->provider = new \OAuth2\Google(array(
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
));
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('password', array('username' => 'mock_username', 'password' => 'mock_password'));
$this->assertInstanceOf('League\OAuth2\Client\Token\AccessToken', $token);
$grant = new \League\OAuth2\Client\Grant\Password();
$this->assertEquals('password', (string) $grant);
$this->assertInstanceOf('\OAuth2\AccessToken', $token);
}
/**

View File

@ -1,168 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
use Mockery as m;
class AbstractProviderTest extends \PHPUnit_Framework_TestCase
{
/**
* @var AbstractProvider
*/
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidGrantString()
{
$this->provider->getAccessToken('invalid_grant', ['invalid_parameter' => 'none']);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidGrantObject()
{
$grant = new \StdClass();
$this->provider->getAccessToken($grant, ['invalid_parameter' => 'none']);
}
public function testAuthorizationUrlStateParam()
{
$this->assertContains('state=XXX', $this->provider->getAuthorizationUrl([
'state' => 'XXX'
]));
}
/**
* Tests https://github.com/thephpleague/oauth2-client/issues/134
*/
public function testConstructorSetsProperties()
{
$options = [
'clientId' => '1234',
'clientSecret' => '4567',
'redirectUri' => 'http://example.org/redirect',
'state' => 'foo',
'name' => 'bar',
'uidKey' => 'mynewuid',
'scopes' => ['a', 'b', 'c'],
'method' => 'get',
'scopeSeparator' => ';',
'responseType' => 'csv',
'headers' => ['Foo' => 'Bar'],
];
$mockProvider = new MockProvider($options);
foreach ($options as $key => $value) {
$this->assertEquals($value, $mockProvider->{$key});
}
}
public function testSetRedirectHandler()
{
$this->testFunction = false;
$callback = function ($url) {
$this->testFunction = $url;
};
$this->provider->setRedirectHandler($callback);
$this->provider->authorize('http://test.url/');
$this->assertNotFalse($this->testFunction);
}
/**
* @param $response
*
* @dataProvider userPropertyProvider
*/
public function testGetUserProperties($response, $name = null, $email = null, $id = null)
{
$token = new AccessToken(['access_token' => 'abc', 'expires_in' => 3600]);
$provider = $this->getMockForAbstractClass(
'\League\OAuth2\Client\Provider\AbstractProvider',
[
[
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]
]
);
/**
* @var $provider AbstractProvider
*/
$this->assertEquals($name, $provider->userScreenName($response, $token));
$this->assertEquals($email, $provider->userEmail($response, $token));
$this->assertEquals($id, $provider->userUid($response, $token));
}
public function userPropertyProvider()
{
$response = new \stdClass();
$response->id = 1;
$response->email = 'test@example.com';
$response->name = 'test';
$response2 = new \stdClass();
$response2->id = null;
$response2->email = null;
$response2->name = null;
$response3 = new \stdClass();
return [
[$response, 'test', 'test@example.com', 1],
[$response2],
[$response3],
];
}
}
class MockProvider extends \League\OAuth2\Client\Provider\AbstractProvider
{
public function urlAuthorize()
{
return '';
}
public function urlAccessToken()
{
return '';
}
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
{
return '';
}
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
{
return '';
}
}

View File

@ -1,98 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
class FacebookTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Facebook([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$this->assertEquals('/oauth/access_token', $uri['path']);
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
# print_r($token);die();
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
public function testScopes()
{
$this->assertEquals(['offline_access', 'email', 'read_stream'], $this->provider->getScopes());
}
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->andReturn('{"id": 12345, "name": "mock_name", "username": "mock_username", "first_name": "mock_first_name", "last_name": "mock_last_name", "email": "mock_email", "Location": "mock_home", "bio": "mock_description", "link": "mock_facebook_url"}');
$getResponse->shouldReceive('getInfo')->andReturn(['url' => 'mock_image_url']);
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(6);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->andReturn($getResponse);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals(['mock_first_name', 'mock_last_name'], $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals('mock_email', $user->email);
}
}

View File

@ -1,175 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
class GithubTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Github([
'clientId' => 'mock',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$this->assertEquals('/login/oauth/access_token', $uri['path']);
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
public function testGetAccessTokenSetResultUid()
{
$this->provider->uidKey = 'otherKey';
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('{1234}', $token->uid);
}
public function testScopes()
{
$this->provider->setScopes(['user', 'repo']);
$this->assertEquals(['user', 'repo'], $this->provider->getScopes());
}
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"id": 12345, "login": "mock_login", "name": "mock_name", "email": "mock_email"}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals('mock_name', $this->provider->getUserScreenName($token));
$this->assertEquals('mock_name', $user->name);
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
}
public function testGithubDomainUrls()
{
$client = m::mock('Guzzle\Service\Client');
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals($this->provider->domain.'/login/oauth/authorize', $this->provider->urlAuthorize());
$this->assertEquals($this->provider->domain.'/login/oauth/access_token', $this->provider->urlAccessToken());
$this->assertEquals($this->provider->apiDomain.'/user?access_token=mock_access_token', $this->provider->urlUserDetails($token));
$this->assertEquals($this->provider->apiDomain.'/user/emails?access_token=mock_access_token', $this->provider->urlUserEmails($token));
}
public function testGithubEnterpriseDomainUrls()
{
$this->provider->domain = 'https://github.company.com';
$client = m::mock('Guzzle\Service\Client');
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals($this->provider->domain.'/login/oauth/authorize', $this->provider->urlAuthorize());
$this->assertEquals($this->provider->domain.'/login/oauth/access_token', $this->provider->urlAccessToken());
$this->assertEquals($this->provider->domain.'/api/v3/user?access_token=mock_access_token', $this->provider->urlUserDetails($token));
$this->assertEquals($this->provider->domain.'/api/v3/user/emails?access_token=mock_access_token', $this->provider->urlUserEmails($token));
}
public function testUserEmails()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&uid=1');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(1)->andReturn('[{"email":"mock_email_1","primary":false,"verified":true},{"email":"mock_email_2","primary":false,"verified":true},{"email":"mock_email_3","primary":true,"verified":true}]');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(2);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(1)->andReturn($getResponse);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$emails = $this->provider->getUserEmails($token);
$this->assertInternalType('array', $emails);
$this->assertCount(3, $emails);
$this->assertEquals('mock_email_3', $emails[2]->email);
$this->assertTrue($emails[2]->primary);
}
}

View File

@ -1,95 +0,0 @@
<?php
namespace League\OAuth2\Client\Test\Provider;
use Mockery as m;
class VkontakteTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \League\OAuth2\Client\Provider\Vkontakte([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function tearDown()
{
m::close();
parent::tearDown();
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$this->assertEquals('/access_token', $uri['path']);
}
public function testGetAccessToken()
{
$response = m::mock('Guzzle\Http\Message\Response');
$response->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(1);
$client->shouldReceive('post->send')->times(1)->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
public function testScopes()
{
$this->assertEquals([], $this->provider->getScopes());
}
public function testUserData()
{
$postResponse = m::mock('Guzzle\Http\Message\Response');
$postResponse->shouldReceive('getBody')->times(1)->andReturn('{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$getResponse = m::mock('Guzzle\Http\Message\Response');
$getResponse->shouldReceive('getBody')->times(4)->andReturn('{"response": [{"uid": 12345, "nickname": "mock_nickname", "screen_name": "mock_name", "first_name": "mock_first_name", "last_name": "mock_last_name", "email": "mock_email", "country": "UK", "status": "mock_status", "photo_200_orig": "mock_image_url"}]}');
$client = m::mock('Guzzle\Service\Client');
$client->shouldReceive('setBaseUrl')->times(5);
$client->shouldReceive('post->send')->times(1)->andReturn($postResponse);
$client->shouldReceive('get->send')->times(4)->andReturn($getResponse);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $this->provider->getUserUid($token));
$this->assertEquals(['mock_first_name', 'mock_last_name'], $this->provider->getUserScreenName($token));
$this->assertEquals('mock_email', $this->provider->getUserEmail($token));
$this->assertEquals('mock_email', $user->email);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace OAuth2\Test;
class RefreshTokenTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Google([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function testGetAccessToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertInstanceOf('OAuth2\AccessToken', $token);
$newToken = $this->provider->getAccessToken('refresh_token', ['refresh_token' => $token->refreshToken]);
$this->assertInstanceOf('OAuth2\AccessToken', $newToken);
}
/**
* @expectedException BadMethodCallException
*/
public function testInvalidRefreshToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$refreshToken = $this->provider->getAccessToken('refresh_token', ['invalid_refresh_token' => $token->refreshToken]);
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace OAuth2\Test;
class VkontakteTest extends \PHPUnit_Framework_TestCase
{
protected $provider;
protected function setUp()
{
$this->provider = new \OAuth2\Vkontakte([
'clientId' => 'mock_client_id',
'clientSecret' => 'mock_secret',
'redirectUri' => 'none',
]);
}
public function testAuthorizationUrl()
{
$url = $this->provider->getAuthorizationUrl();
$uri = parse_url($url);
parse_str($uri['query'], $query);
$this->assertArrayHasKey('client_id', $query);
$this->assertArrayHasKey('redirect_uri', $query);
$this->assertArrayHasKey('state', $query);
$this->assertArrayHasKey('scope', $query);
$this->assertArrayHasKey('response_type', $query);
$this->assertArrayHasKey('approval_prompt', $query);
$this->assertNotNull($this->provider->state);
}
public function testUrlAccessToken()
{
$url = $this->provider->urlAccessToken();
$uri = parse_url($url);
$this->assertEquals('/access_token', $uri['path']);
}
public function testGetAccessToken()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$this->assertEquals('mock_access_token', $token->accessToken);
$this->assertLessThanOrEqual(time() + 3600, $token->expires);
$this->assertGreaterThanOrEqual(time(), $token->expires);
$this->assertEquals('mock_refresh_token', $token->refreshToken);
$this->assertEquals('1', $token->uid);
}
public function testScopes()
{
$this->assertEquals([], $this->provider->getScopes());
}
public function testUserData()
{
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"access_token": "mock_access_token", "expires": 3600, "refresh_token": "mock_refresh_token", "uid": 1}');
\OAuth2\CurlMock::addPendingResponse(true, "200 OK", '', '{"response": [{"uid": 12345, "nickname": "mock_nickname", "screen_name": "mock_name", "first_name": "mock_first_name", "last_name": "mock_last_name", "email": "mock_email", "country": "UK", "status": "mock_status", "photo_200_orig": "mock_image_url"}]}');
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
$user = $this->provider->getUserDetails($token);
$this->assertEquals(12345, $user['uid']);
$this->assertEquals('mock_first_name', $user['firstname']);
$this->assertEquals('mock_last_name', $user['lastname']);
$this->assertEquals('mock_email', $user['email']);
$this->assertEquals('mock_image_url', $user['image_url']);
}
}