Skip to content

Commit

Permalink
Moved fetching Apple JWT keys from token to provider
Browse files Browse the repository at this point in the history
Since AccessToken is serialized in specific set-ups, existence of the httpClient leads to problems, since closures are not serializable. Also, it's not necessary to keep the httpClient there, since it's only used in the constructor.

Fixes #26, #28
  • Loading branch information
tjveldhuizen committed Aug 3, 2021
1 parent f6fe8c0 commit 5f20997
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 32 deletions.
17 changes: 16 additions & 1 deletion src/Provider/Apple.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace League\OAuth2\Client\Provider;

use Exception;
use Firebase\JWT\JWK;
use InvalidArgumentException;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Key\LocalFileReference;
Expand Down Expand Up @@ -77,7 +78,21 @@ public function __construct(array $options = [], array $collaborators = [])
*/
protected function createAccessToken(array $response, AbstractGrant $grant)
{
return new AppleAccessToken($this->getHttpClient(), $response);
return new AppleAccessToken($this->getAppleKeys(), $response);
}

/**
* @return string[] Apple's JSON Web Keys
*/
private function getAppleKeys()
{
$response = $this->httpClient->request('GET', 'https://appleid.apple.com/auth/keys');

if ($response) {
return JWK::parseKeySet(json_decode($response->getBody()->getContents(), true));
}

return [];
}

/**
Expand Down
26 changes: 2 additions & 24 deletions src/Token/AppleAccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,24 @@ class AppleAccessToken extends AccessToken
*/
protected $isPrivateEmail;

/**
* @var ClientInterface
*/
protected $httpClient;

/**
* Constructs an access token.
*
* @param ClientInterface $httpClient the http client to use
* @param string[] $keys Valid Apple JWT keys
* @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($httpClient, array $options = [])
public function __construct(array $keys, array $options = [])
{
$this->httpClient = $httpClient;

if (array_key_exists('refresh_token', $options)) {
if (empty($options['id_token'])) {
throw new InvalidArgumentException('Required option not passed: "id_token"');
}

$decoded = null;
$keys = $this->getAppleKey();
$last = end($keys);
foreach ($keys as $key) {
try {
Expand Down Expand Up @@ -88,20 +80,6 @@ public function __construct($httpClient, array $options = [])
}
}

/**
* @return array Apple's JSON Web Key
*/
protected function getAppleKey()
{
$response = $this->httpClient->request('GET', 'https://appleid.apple.com/auth/keys');

if ($response) {
return JWK::parseKeySet(json_decode($response->getBody()->getContents(), true));
}

return [];
}

/**
* @return string
*/
Expand Down
9 changes: 2 additions & 7 deletions test/src/Token/AppleAccessTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@ public function testCreatingAccessToken()
'sub' => '123.abc.123'
]);

$externalJWKMock = m::mock('overload:Firebase\JWT\JWK');
$externalJWKMock->shouldReceive('parseKeySet')
->once()
->andReturn(['examplekey']);

$accessToken = new AppleAccessToken($this->getClient(1), [
$accessToken = new AppleAccessToken(['examplekey'], [
'access_token' => 'access_token',
'token_type' => 'Bearer',
'expires_in' => 3600,
Expand All @@ -42,7 +37,7 @@ public function testCreatingAccessToken()

public function testCreatingRefreshToken()
{
$refreshToken = new AppleAccessToken($this->getClient(0), [
$refreshToken = new AppleAccessToken([], [
'access_token' => 'access_token',
'token_type' => 'Bearer',
'expires_in' => 3600
Expand Down

0 comments on commit 5f20997

Please sign in to comment.