8 Commits

Author SHA1 Message Date
Patrick Bußmann 754769b229 Fixed #9 - Added compatibility for refresh tokens 2020-07-15 02:31:30 +02:00
Patrick Bußmann 413d7dd2ea Fixed #12 - Bug when $_GET['user'] or $_POST['user'] is empty 2020-07-15 01:39:36 +02:00
François-Xavier de Guillebon daa9d05ecf Fix class JWK not found 2020-07-01 18:41:50 +02:00
Patrick Bußmann b5db19c8a0 Merge pull request #7 from adrianbardan/master
Replace fproject/php-jwt with firebase/php-jwt
2020-06-24 11:46:09 +02:00
Adi Bardan bf39ebf16a replace fproject/php-jwt with firebase/php-jwt 2020-05-20 13:09:19 +02:00
Patrick Bußmann 134ec39429 Fixed bug with usage of JSON web key set of apple 2020-02-13 03:43:29 +01:00
Patrick Bußmann 519e67995c Merge pull request #2 from NaxYo/patch-1
Avoiding crash on access denied
2020-01-21 17:56:03 +01:00
Ignacio G 960790987a Avoiding crash on access denied
Checking for array fields on access denied response in order to avoid `Undefined index: code` exception
2020-01-08 14:11:24 +10:00
6 changed files with 128 additions and 19 deletions
+19 -1
View File
@@ -1,7 +1,7 @@
# Changelog
All Notable changes to `oauth2-apple` will be documented in this file
## 0.3.0 - 201X-XX-XX
## 0.3.0 - 202X-XX-XX
### Added
- Nothing
@@ -18,6 +18,24 @@ All Notable changes to `oauth2-apple` will be documented in this file
### Security
- Nothing
## 0.2.1 - 2020-02-13
### Added
- Nothing
### Deprecated
- Nothing
### Fixed
- Handling of Apples JSON Web Key Set
- Undefined index: code [#4](https://github.com/patrickbussmann/oauth2-apple/pull/4) (thanks to [Darlinkster](https://github.com/Darlinkster))
### Removed
- Nothing
### Security
- Nothing
## 0.2.0 - 2019-10-31
### Added
+1 -1
View File
@@ -21,7 +21,7 @@
"require": {
"league/oauth2-client": "^2.0",
"ext-json": "*",
"fproject/php-jwt": "^4.0",
"firebase/php-jwt": "^5.2",
"lcobucci/jwt": "^3.3"
},
"require-dev": {
+3 -3
View File
@@ -113,7 +113,7 @@ class Apple extends AbstractProvider
protected function fetchResourceOwnerDetails(AccessToken $token)
{
return json_decode(array_key_exists('user', $_GET) ? $_GET['user']
: (array_key_exists('user', $_POST) ? $_POST['user'] : '[]'), true);
: (array_key_exists('user', $_POST) ? $_POST['user'] : '[]'), true) ?: [];
}
/**
@@ -174,8 +174,8 @@ class Apple extends AbstractProvider
{
if ($response->getStatusCode() >= 400) {
throw new AppleAccessDeniedException(
$data['error'] ?: $response->getReasonPhrase(),
$data['code'] ?: $response->getStatusCode(),
array_key_exists('error', $data) ? $data['error'] : $response->getReasonPhrase(),
array_key_exists('code', $data) ? $data['code'] : $response->getStatusCode(),
$response
);
}
+32 -13
View File
@@ -26,27 +26,46 @@ class AppleAccessToken extends AccessToken
/**
* Constructs an access token.
*
* @param array $options An array of options returned by the service provider
* @param array $options An array of options returned by the service provider
* in the access token request. The `access_token` option is required.
* @throws InvalidArgumentException if `access_token` is not provided in `$options`.
*
* @throws \Exception
*/
public function __construct(array $options = [])
{
if (empty($options['id_token'])) {
throw new InvalidArgumentException('Required option not passed: "id_token"');
}
if (array_key_exists('refresh_token', $options)) {
if (empty($options['id_token'])) {
throw new InvalidArgumentException('Required option not passed: "id_token"');
}
$decoded = JWT::decode($options['id_token'], $this->getAppleKey(), ['RS256']);
$payload = json_decode(json_encode($decoded), true);
$decoded = null;
$keys = $this->getAppleKey();
$last = end($keys);
foreach ($keys as $key) {
try {
$decoded = JWT::decode($options['id_token'], $key, ['RS256']);
break;
} catch (\Exception $exception) {
if ($last === $key) {
throw $exception;
}
}
}
if (null === $decoded) {
throw new \Exception('Got no data within "id_token"!');
}
$payload = json_decode(json_encode($decoded), true);
$options['resource_owner_id'] = $payload['sub'];
$options['resource_owner_id'] = $payload['sub'];
if (isset($payload['email_verified']) && $payload['email_verified']) {
$options['email'] = $payload['email'];
}
if (isset($payload['email_verified']) && $payload['email_verified']) {
$options['email'] = $payload['email'];
}
if (isset($payload['is_private_email'])) {
$this->isPrivateEmail = $payload['is_private_email'];
if (isset($payload['is_private_email'])) {
$this->isPrivateEmail = $payload['is_private_email'];
}
}
parent::__construct($options);
@@ -65,7 +84,7 @@ class AppleAccessToken extends AccessToken
*/
protected function getAppleKey()
{
return JWK::parseKeySet(file_get_contents('https://appleid.apple.com/auth/keys'))['AIDOPK1'];
return JWK::parseKeySet(json_decode(file_get_contents('https://appleid.apple.com/auth/keys'), true));
}
/**
+16 -1
View File
@@ -171,7 +171,7 @@ class AppleTest extends \PHPUnit_Framework_TestCase
]);
}
public function testFechtingOwnerDetails()
public function testFetchingOwnerDetails()
{
$class = new \ReflectionClass($this->provider);
$method = $class->getMethod('fetchResourceOwnerDetails');
@@ -186,6 +186,21 @@ class AppleTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($arr, $data);
}
/**
* @see https://github.com/patrickbussmann/oauth2-apple/issues/12
*/
public function testFetchingOwnerDetailsIssue12()
{
$class = new \ReflectionClass($this->provider);
$method = $class->getMethod('fetchResourceOwnerDetails');
$method->setAccessible(true);
$_POST['user'] = '';
$data = $method->invokeArgs($this->provider, [new AccessToken(['access_token' => 'hello'])]);
$this->assertEquals([], $data);
}
/**
* @expectedException Exception
*/
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace League\OAuth2\Client\Test\Token;
use League\OAuth2\Client\Token\AppleAccessToken;
use PHPUnit\Framework\TestCase;
use Mockery as m;
class AppleAccessTokenTest extends TestCase
{
public function tearDown()
{
m::close();
parent::tearDown();
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testCreatingAccessToken()
{
$externalJWTMock = m::mock('overload:Firebase\JWT\JWT');
$externalJWTMock->shouldReceive('decode')
->with('something', 'examplekey', ['RS256'])
->once()
->andReturn([
'sub' => '123.abc.123'
]);
$externalJWKMock = m::mock('overload:Firebase\JWT\JWK');
$externalJWKMock->shouldReceive('parseKeySet')
->once()
->andReturn(['examplekey']);
$accessToken = new AppleAccessToken([
'access_token' => 'access_token',
'token_type' => 'Bearer',
'expires_in' => 3600,
'refresh_token' => 'abc.0.def',
'id_token' => 'something'
]);
$this->assertEquals('something', $accessToken->getIdToken());
$this->assertEquals('123.abc.123', $accessToken->getResourceOwnerId());
$this->assertEquals('access_token', $accessToken->getToken());
}
public function testCreatingRefreshToken()
{
$refreshToken = new AppleAccessToken([
'access_token' => 'access_token',
'token_type' => 'Bearer',
'expires_in' => 3600
]);
$this->assertEquals('access_token', $refreshToken->getToken());
}
}