mirror of
https://github.com/code-rhapsodie/oauth2-apple.git
synced 2026-04-29 14:43:11 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 754769b229 | |||
| 413d7dd2ea | |||
| daa9d05ecf | |||
| b5db19c8a0 | |||
| bf39ebf16a | |||
| 134ec39429 | |||
| 519e67995c | |||
| 960790987a |
+19
-1
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user