Merge branch 'master' into 1.0
Conflicts: src/Provider/AbstractProvider.php test/src/Exception/IDPExceptionTest.php test/src/Provider/GithubTest.php test/src/Provider/GoogleTest.php test/src/Provider/LinkedInTest.php1.0
commit
299373fba6
|
@ -8,8 +8,8 @@ php:
|
|||
|
||||
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
|
||||
- travis_retry composer require satooshi/php-coveralls:dev-master --no-update
|
||||
- travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
|
|
|
@ -138,6 +138,7 @@ so please help them out with a pull request if you notice this.
|
|||
- [Twitch.tv](https://github.com/tpavlek/oauth2-twitch)
|
||||
- [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
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ class IDPException extends \Exception
|
|||
|
||||
$code = isset($result['code']) ? $result['code'] : 0;
|
||||
|
||||
if (isset($result['error'])) {
|
||||
if (isset($result['error']) && $result['error'] !== '') {
|
||||
// OAuth 2.0 Draft 10 style
|
||||
$message = $result['error'];
|
||||
} elseif (isset($result['message'])) {
|
||||
} elseif (isset($result['message']) && $result['message'] !== '') {
|
||||
// cURL style
|
||||
$message = $result['message'];
|
||||
} else {
|
||||
|
@ -25,6 +25,11 @@ class IDPException extends \Exception
|
|||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
public function getResponseBody()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
$result = 'Exception';
|
||||
|
|
|
@ -32,7 +32,9 @@ abstract class AbstractProvider implements ProviderInterface
|
|||
|
||||
public $responseType = 'json';
|
||||
|
||||
public $headers = null;
|
||||
public $headers = [];
|
||||
|
||||
public $authorizationHeader;
|
||||
|
||||
/**
|
||||
* @var HttpAdapterInterface
|
||||
|
@ -325,15 +327,17 @@ abstract class AbstractProvider implements ProviderInterface
|
|||
{
|
||||
$url = $this->urlUserDetails($token);
|
||||
|
||||
return $this->fetchProviderData($url);
|
||||
$headers = $this->getHeaders($token);
|
||||
|
||||
return $this->fetchProviderData($url, $headers);
|
||||
}
|
||||
|
||||
protected function fetchProviderData($url)
|
||||
protected function fetchProviderData($url, array $headers = [])
|
||||
{
|
||||
try {
|
||||
$client = $this->getHttpClient();
|
||||
|
||||
$httpResponse = $client->get($url, $this->headers ?: []);
|
||||
$httpResponse = $client->get($url, ['headers' => $headers]);
|
||||
|
||||
$response = (string) $httpResponse->getBody();
|
||||
} catch (HttpAdapterException $e) {
|
||||
|
@ -346,6 +350,24 @@ abstract class AbstractProvider implements ProviderInterface
|
|||
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(Closure $handler)
|
||||
{
|
||||
$this->redirectHandler = $handler;
|
||||
|
|
|
@ -6,13 +6,7 @@ use League\OAuth2\Client\Entity\User;
|
|||
|
||||
class Eventbrite extends AbstractProvider
|
||||
{
|
||||
public function __construct($options)
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->headers = [
|
||||
'Authorization' => 'Bearer',
|
||||
];
|
||||
}
|
||||
public $authorizationHeader = 'Bearer';
|
||||
|
||||
public function urlAuthorize()
|
||||
{
|
||||
|
@ -26,7 +20,7 @@ class Eventbrite extends AbstractProvider
|
|||
|
||||
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
{
|
||||
return 'https://www.eventbrite.com/json/user_get?access_token='.$token;
|
||||
return 'https://www.eventbrite.com/json/user_get';
|
||||
}
|
||||
|
||||
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
namespace League\OAuth2\Client\Provider;
|
||||
|
||||
use League\OAuth2\Client\Entity\User;
|
||||
use League\OAuth2\Client\Token\AccessToken;
|
||||
|
||||
class Github extends AbstractProvider
|
||||
{
|
||||
public $responseType = 'string';
|
||||
|
||||
public $authorizationHeader = 'token';
|
||||
|
||||
public $domain = 'https://github.com';
|
||||
|
||||
public $apiDomain = 'https://api.github.com';
|
||||
|
@ -22,23 +25,23 @@ class Github extends AbstractProvider
|
|||
return $this->domain.'/login/oauth/access_token';
|
||||
}
|
||||
|
||||
public function urlUserDetails(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function urlUserDetails(AccessToken $token)
|
||||
{
|
||||
if ($this->domain === 'https://github.com') {
|
||||
return $this->apiDomain.'/user?access_token='.$token;
|
||||
return $this->apiDomain.'/user';
|
||||
}
|
||||
return $this->domain.'/api/v3/user?access_token='.$token;
|
||||
return $this->domain.'/api/v3/user';
|
||||
}
|
||||
|
||||
public function urlUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function urlUserEmails(AccessToken $token)
|
||||
{
|
||||
if ($this->domain === 'https://github.com') {
|
||||
return $this->apiDomain.'/user/emails?access_token='.$token;
|
||||
return $this->apiDomain.'/user/emails';
|
||||
}
|
||||
return $this->domain.'/api/v3/user/emails?access_token='.$token;
|
||||
return $this->domain.'/api/v3/user/emails';
|
||||
}
|
||||
|
||||
public function userDetails($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function userDetails($response, AccessToken $token)
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
|
@ -58,37 +61,39 @@ class Github extends AbstractProvider
|
|||
return $user;
|
||||
}
|
||||
|
||||
public function userUid($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function userUid($response, AccessToken $token)
|
||||
{
|
||||
return $response->id;
|
||||
}
|
||||
|
||||
public function getUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function getUserEmails(AccessToken $token)
|
||||
{
|
||||
$response = $this->fetchUserEmails($token);
|
||||
|
||||
return $this->userEmails(json_decode($response), $token);
|
||||
}
|
||||
|
||||
public function userEmail($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function userEmail($response, AccessToken $token)
|
||||
{
|
||||
return isset($response->email) && $response->email ? $response->email : null;
|
||||
}
|
||||
|
||||
public function userEmails($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function userEmails($response, AccessToken $token)
|
||||
{
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function userScreenName($response, \League\OAuth2\Client\Token\AccessToken $token)
|
||||
public function userScreenName($response, AccessToken $token)
|
||||
{
|
||||
return $response->name;
|
||||
}
|
||||
|
||||
protected function fetchUserEmails(\League\OAuth2\Client\Token\AccessToken $token)
|
||||
protected function fetchUserEmails(AccessToken $token)
|
||||
{
|
||||
$url = $this->urlUserEmails($token);
|
||||
|
||||
return $this->fetchProviderData($url);
|
||||
$headers = $this->getHeaders($token);
|
||||
|
||||
return $this->fetchProviderData($url, $headers);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,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
|
||||
|
@ -60,7 +62,7 @@ class Google extends AbstractProvider
|
|||
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)
|
||||
|
|
|
@ -9,6 +9,7 @@ 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,8 +27,8 @@ 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)
|
||||
|
|
|
@ -24,6 +24,8 @@ interface ProviderInterface
|
|||
|
||||
public function getAccessToken($grant = 'authorization_code', $params = []);
|
||||
|
||||
public function getHeaders($token = null);
|
||||
|
||||
public function getUserDetails(AccessToken $token);
|
||||
|
||||
public function getUserUid(AccessToken $token);
|
||||
|
|
|
@ -41,4 +41,41 @@ class IDPExceptionTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$this->assertEquals('message: 404: message', (string)$exception);
|
||||
}
|
||||
|
||||
public function testGetResponseBody()
|
||||
{
|
||||
$exception = new IDPException(array('error' => 'message', 'code' => 404));
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'error' => 'message',
|
||||
'code' => 404
|
||||
],
|
||||
$exception->getResponseBody()
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmptyMessage()
|
||||
{
|
||||
$exception = new IDPException(array('error' => 'error_message', 'message' => ''));
|
||||
$this->assertEquals('error_message', $exception->getMessage());
|
||||
}
|
||||
|
||||
public function testNonEmptyErrorAndMessage()
|
||||
{
|
||||
$exception = new IDPException(array('error' => 'error_message', 'message' => 'message'));
|
||||
$this->assertEquals('error_message', $exception->getMessage());
|
||||
}
|
||||
|
||||
public function testEmptyError()
|
||||
{
|
||||
$exception = new IDPException(array('error' => '', 'message' => 'message'));
|
||||
$this->assertEquals('message', $exception->getMessage());
|
||||
}
|
||||
|
||||
public function testEmptyErrorAndMessage()
|
||||
{
|
||||
$exception = new IDPException(array('error' => '', 'message' => ''));
|
||||
$this->assertEquals('Unknown Error.', $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ class AbstractProviderTest extends \PHPUnit_Framework_TestCase
|
|||
'scopeSeparator' => ';',
|
||||
'responseType' => 'csv',
|
||||
'headers' => ['Foo' => 'Bar'],
|
||||
'authorizationHeader' => 'Bearer',
|
||||
];
|
||||
|
||||
$mockProvider = new MockProvider($options);
|
||||
|
@ -150,6 +151,32 @@ class AbstractProviderTest extends \PHPUnit_Framework_TestCase
|
|||
[$response3],
|
||||
];
|
||||
}
|
||||
|
||||
public function getHeadersTest()
|
||||
{
|
||||
$provider = $this->getMockForAbstractClass(
|
||||
'\League\OAuth2\Client\Provider\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 AccessToken(['access_token' => 'xyz', 'expires_in' => 3600]);
|
||||
$this->assertEquals(['Authorization' => 'Bearer xyz'], $provider->getHeaders($token));
|
||||
}
|
||||
}
|
||||
|
||||
class MockProvider extends \League\OAuth2\Client\Provider\AbstractProvider
|
||||
|
|
|
@ -114,8 +114,8 @@ class GithubTest extends ConcreteProviderTest
|
|||
|
||||
$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));
|
||||
$this->assertEquals($this->provider->apiDomain.'/user', $this->provider->urlUserDetails($token));
|
||||
$this->assertEquals($this->provider->apiDomain.'/user/emails', $this->provider->urlUserEmails($token));
|
||||
}
|
||||
|
||||
public function testGithubEnterpriseDomainUrls()
|
||||
|
@ -130,8 +130,8 @@ class GithubTest extends ConcreteProviderTest
|
|||
|
||||
$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));
|
||||
$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()
|
||||
|
|
|
@ -56,8 +56,6 @@ class GoogleTest extends ConcreteProviderTest
|
|||
|
||||
$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);
|
||||
|
|
|
@ -49,8 +49,6 @@ class LinkedInTest extends ConcreteProviderTest
|
|||
|
||||
$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);
|
||||
|
|
Loading…
Reference in New Issue