From 3e5c9f163b6e45c88afc437d41ecb106d8a9951f Mon Sep 17 00:00:00 2001 From: Brent Shaffer Date: Thu, 30 Mar 2023 13:35:40 -0600 Subject: [PATCH] feat: access granted scopes (#441) --- src/Credentials/UserRefreshCredentials.php | 10 ++++++ src/OAuth2.php | 33 +++++++++++++++++++ .../UserRefreshCredentialsTest.php | 14 ++++++++ tests/OAuth2Test.php | 2 ++ 4 files changed, 59 insertions(+) diff --git a/src/Credentials/UserRefreshCredentials.php b/src/Credentials/UserRefreshCredentials.php index dc009dd22..e2f32d87f 100644 --- a/src/Credentials/UserRefreshCredentials.php +++ b/src/Credentials/UserRefreshCredentials.php @@ -139,4 +139,14 @@ public function getQuotaProject() { return $this->quotaProject; } + + /** + * Get the granted scopes (if they exist) for the last fetched token. + * + * @return string|null + */ + public function getGrantedScope() + { + return $this->auth->getGrantedScope(); + } } diff --git a/src/OAuth2.php b/src/OAuth2.php index d418b8042..4ac296ad5 100644 --- a/src/OAuth2.php +++ b/src/OAuth2.php @@ -215,6 +215,13 @@ class OAuth2 implements FetchAuthTokenInterface */ private $idToken; + /** + * The scopes granted to the current access token + * + * @var string + */ + private $grantedScope; + /** * The lifetime in seconds of the current access token. * @@ -544,6 +551,9 @@ public function fetchAuthToken(callable $httpHandler = null) $response = $httpHandler($this->generateCredentialsRequest()); $credentials = $this->parseTokenResponse($response); $this->updateToken($credentials); + if (isset($credentials['scope'])) { + $this->setGrantedScope($credentials['scope']); + } return $credentials; } @@ -640,6 +650,7 @@ public function updateToken(array $config) 'expires_in' => null, 'expires_at' => null, 'issued_at' => null, + 'scope' => null, ], $config); $this->setExpiresAt($opts['expires_at']); @@ -652,6 +663,7 @@ public function updateToken(array $config) $this->setAccessToken($opts['access_token']); $this->setIdToken($opts['id_token']); + // The refresh token should only be updated if a value is explicitly // passed in, as some access token responses do not include a refresh // token. @@ -1335,6 +1347,27 @@ public function setIdToken($idToken) $this->idToken = $idToken; } + /** + * Get the granted scopes (if they exist) for the last fetched token. + * + * @return string|null + */ + public function getGrantedScope() + { + return $this->grantedScope; + } + + /** + * Sets the current ID token. + * + * @param string $grantedScope + * @return void + */ + public function setGrantedScope($grantedScope) + { + $this->grantedScope = $grantedScope; + } + /** * Gets the refresh token associated with the current access token. * diff --git a/tests/Credentials/UserRefreshCredentialsTest.php b/tests/Credentials/UserRefreshCredentialsTest.php index fd4649d5c..117a266c5 100644 --- a/tests/Credentials/UserRefreshCredentialsTest.php +++ b/tests/Credentials/UserRefreshCredentialsTest.php @@ -253,6 +253,20 @@ public function testCanFetchCredsOK() $tokens = $sa->fetchAuthToken($httpHandler); $this->assertEquals($testJson, $tokens); } + + public function testGetGrantedScope() + { + $responseJson = json_encode(['scope' => 'scope/1 scope/2']); + $httpHandler = getHandler([ + buildResponse(200, [], Utils::streamFor($responseJson)), + ]); + $sa = new UserRefreshCredentials( + '', + createURCTestJson() + ); + $sa->fetchAuthToken($httpHandler); + $this->assertEquals('scope/1 scope/2', $sa->getGrantedScope()); + } } class URCGetQuotaProjectTest extends TestCase diff --git a/tests/OAuth2Test.php b/tests/OAuth2Test.php index 0a1f18cd4..a365b47eb 100644 --- a/tests/OAuth2Test.php +++ b/tests/OAuth2Test.php @@ -756,6 +756,7 @@ public function testUpdatesTokenFieldsOnFetch() 'access_token' => 'an_access_token', 'id_token' => 'an_id_token', 'refresh_token' => 'a_refresh_token', + 'scope' => 'scope1 scope2', ]; $json = json_encode($wanted_updates); $httpHandler = getHandler([ @@ -775,6 +776,7 @@ public function testUpdatesTokenFieldsOnFetch() $this->assertEquals('an_access_token', $o->getAccessToken()); $this->assertEquals('an_id_token', $o->getIdToken()); $this->assertEquals('a_refresh_token', $o->getRefreshToken()); + $this->assertEquals('scope1 scope2', $o->getGrantedScope()); } public function testUpdatesTokenFieldsOnFetchMissingRefreshToken()