diff --git a/src/Core/AccessToken.php b/src/Core/AccessToken.php index 6bcb04c5..b2b8ab02 100644 --- a/src/Core/AccessToken.php +++ b/src/Core/AccessToken.php @@ -74,9 +74,6 @@ final class AccessToken extends SettingsContainerAbstract{ /** * The scopes that are attached to this token (OAuth2) - * - * Please note that the scopes have to be stored manually after receiving the token - * as the initial auth URL request data is discarded before the callback comes in. */ protected array $scopes = []; diff --git a/src/Core/OAuth2Provider.php b/src/Core/OAuth2Provider.php index c68da8d5..241c6373 100644 --- a/src/Core/OAuth2Provider.php +++ b/src/Core/OAuth2Provider.php @@ -16,7 +16,7 @@ use chillerlan\HTTP\Utils\{MessageUtil, QueryUtil}; use Psr\Http\Message\{RequestInterface, ResponseInterface, UriInterface}; -use function array_merge, base64_encode, date, hash_equals, implode, is_array, json_decode, random_bytes, sha1, sprintf; +use function array_merge, base64_encode, date, explode, hash_equals, implode, is_array, json_decode, random_bytes, sha1, sprintf; use const JSON_THROW_ON_ERROR, PHP_QUERY_RFC1738; /** @@ -110,11 +110,9 @@ protected function parseTokenResponse(ResponseInterface $response):AccessToken{ } foreach(['error_description', 'error'] as $field){ - if(isset($data[$field])){ throw new ProviderException('error retrieving access token: "'.$data[$field].'"'); } - } if(!isset($data['access_token'])){ @@ -127,7 +125,13 @@ protected function parseTokenResponse(ResponseInterface $response):AccessToken{ $token->expires = ($data['expires_in'] ?? AccessToken::EOL_NEVER_EXPIRES); $token->refreshToken = ($data['refresh_token'] ?? null); - unset($data['expires_in'], $data['refresh_token'], $data['access_token']); + if(isset($data['scope']) || isset($data['scopes'])){ + $scope = ($data['scope'] ?? $data['scopes'] ?? []); + + $token->scopes = (is_array($scope)) ? $scope : explode($this->scopesDelimiter, $scope); + } + + unset($data['expires_in'], $data['refresh_token'], $data['access_token'], $data['scope'], $data['scopes']); $token->extraParams = $data; @@ -215,7 +219,11 @@ public function getClientCredentialsToken(array $scopes = null):AccessToken{ } $token = $this->parseTokenResponse($this->http->sendRequest($request)); - $token->scopes = ($scopes ?? []); + + // provider didn't send a set of scopes with the token response, so add the given ones manually + if(empty($token->scopes)){ + $token->scopes = ($scopes ?? []); + } $this->storage->storeAccessToken($token, $this->serviceName); diff --git a/tests/Providers/OAuth2ProviderTestAbstract.php b/tests/Providers/OAuth2ProviderTestAbstract.php index af5435ca..cd6d6b1f 100644 --- a/tests/Providers/OAuth2ProviderTestAbstract.php +++ b/tests/Providers/OAuth2ProviderTestAbstract.php @@ -31,7 +31,7 @@ abstract class OAuth2ProviderTestAbstract extends OAuthProviderTestAbstract{ protected array $testResponses = [ '/oauth2/access_token' => - '{"access_token":"test_access_token","expires_in":3600,"state":"test_state"}', + '{"access_token":"test_access_token","expires_in":3600,"state":"test_state","scope":"some_scope other_scope"}', '/oauth2/refresh_token' => '{"access_token":"test_refreshed_access_token","expires_in":60,"state":"test_state"}', '/oauth2/revoke_token' => @@ -67,6 +67,7 @@ public function testGetAccessToken():void{ $token = $this->provider->getAccessToken('foo', 'test_state'); $this::assertSame('test_access_token', $token->accessToken); + $this::assertSame(['some_scope', 'other_scope'], $token->scopes); $this::assertGreaterThan(time(), $token->expires); }