diff --git a/src/Credentials/ImpersonatedServiceAccountCredentials.php b/src/Credentials/ImpersonatedServiceAccountCredentials.php index 577fe2298..1b4e46eaf 100644 --- a/src/Credentials/ImpersonatedServiceAccountCredentials.php +++ b/src/Credentials/ImpersonatedServiceAccountCredentials.php @@ -37,13 +37,13 @@ class ImpersonatedServiceAccountCredentials extends CredentialsLoader implements protected $sourceCredentials; /** - * Instantiate an instance of ImpersonatedServiceAccountCredentials from a credentials file that has be created with - * the --impersonated-service-account flag. + * Instantiate an instance of ImpersonatedServiceAccountCredentials from a credentials file that + * has be created with the --impersonated-service-account flag. * - * @param string|string[] $scope the scope of the access request, expressed - * either as an Array or as a space-delimited String. + * @param string|string[] $scope The scope of the access request, expressed either as an + * array or as a space-delimited string. * @param string|array $jsonKey JSON credential file path or JSON credentials - * as an associative array + * as an associative array. */ public function __construct( $scope, @@ -59,24 +59,34 @@ public function __construct( } } if (!array_key_exists('service_account_impersonation_url', $jsonKey)) { - throw new \LogicException('json key is missing the service_account_impersonation_url field'); + throw new \LogicException( + 'json key is missing the service_account_impersonation_url field' + ); } if (!array_key_exists('source_credentials', $jsonKey)) { throw new \LogicException('json key is missing the source_credentials field'); } - $this->impersonatedServiceAccountName = $this->getImpersonatedServiceAccountNameFromUrl($jsonKey['service_account_impersonation_url']); + $this->impersonatedServiceAccountName = $this->getImpersonatedServiceAccountNameFromUrl( + $jsonKey['service_account_impersonation_url'] + ); - $this->sourceCredentials = new UserRefreshCredentials($scope, $jsonKey['source_credentials']); + $this->sourceCredentials = new UserRefreshCredentials( + $scope, + $jsonKey['source_credentials'] + ); } /** - * Helper function for extracting the Server Account Name from the URL saved in the account credentials file - * @param $serviceAccountImpersonationUrl string URL from the 'service_account_impersonation_url' field + * Helper function for extracting the Server Account Name from the URL saved in the account + * credentials file. + * + * @param $serviceAccountImpersonationUrl string URL from "service_account_impersonation_url" * @return string Service account email or ID. */ - private function getImpersonatedServiceAccountNameFromUrl(string $serviceAccountImpersonationUrl) - { + private function getImpersonatedServiceAccountNameFromUrl( + string $serviceAccountImpersonationUrl + ): string { $fields = explode('/', $serviceAccountImpersonationUrl); $lastField = end($fields); $splitter = explode(':', $lastField); diff --git a/tests/OAuth2Test.php b/tests/OAuth2Test.php index 7e2c96702..1a7ccdd64 100644 --- a/tests/OAuth2Test.php +++ b/tests/OAuth2Test.php @@ -28,7 +28,7 @@ use PHPUnit\Framework\TestCase; use UnexpectedValueException; -class OAuth2AuthorizationUriTest extends TestCase +class OAuth2Test extends TestCase { private $minimal = [ 'authorizationUri' => 'https://accounts.test.org/insecure/url', @@ -36,6 +36,43 @@ class OAuth2AuthorizationUriTest extends TestCase 'clientId' => 'aClientID', ]; + private $signingMinimal = [ + 'signingKey' => 'example_key', + 'signingAlgorithm' => 'HS256', + 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', + 'issuer' => 'app@example.com', + 'audience' => 'accounts.google.com', + 'clientId' => 'aClientID', + ]; + + private $tokenRequestMinimal = [ + 'tokenCredentialUri' => 'https://tokens_r_us/test', + 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', + 'issuer' => 'app@example.com', + 'audience' => 'accounts.google.com', + 'clientId' => 'aClientID', + ]; + + private $fetchAuthTokenMinimal = [ + 'tokenCredentialUri' => 'https://tokens_r_us/test', + 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', + 'signingKey' => 'example_key', + 'signingAlgorithm' => 'HS256', + 'issuer' => 'app@example.com', + 'audience' => 'accounts.google.com', + 'clientId' => 'aClientID', + ]; + + private $verifyIdTokenMinimal = [ + 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', + 'audience' => 'myaccount.on.host.issuer.com', + 'issuer' => 'an.issuer.com', + 'clientId' => 'myaccount.on.host.issuer.com', + ]; + + /** + * @group oauth2-authorization-uri + */ public function testIsNullIfAuthorizationUriIsNull() { $this->expectException(InvalidArgumentException::class); @@ -44,6 +81,9 @@ public function testIsNullIfAuthorizationUriIsNull() $this->assertNull($o->buildFullAuthorizationUri()); } + /** + * @group oauth2-authorization-uri + */ public function testRequiresTheClientId() { $this->expectException(InvalidArgumentException::class); @@ -55,6 +95,9 @@ public function testRequiresTheClientId() $o->buildFullAuthorizationUri(); } + /** + * @group oauth2-authorization-uri + */ public function testRequiresTheRedirectUri() { $this->expectException(InvalidArgumentException::class); @@ -66,6 +109,9 @@ public function testRequiresTheRedirectUri() $o->buildFullAuthorizationUri(); } + /** + * @group oauth2-authorization-uri + */ public function testCannotHavePromptAndApprovalPrompt() { $this->expectException(InvalidArgumentException::class); @@ -80,6 +126,9 @@ public function testCannotHavePromptAndApprovalPrompt() ]); } + /** + * @group oauth2-authorization-uri + */ public function testCannotHaveInsecureAuthorizationUri() { $this->expectException(InvalidArgumentException::class); @@ -92,6 +141,9 @@ public function testCannotHaveInsecureAuthorizationUri() $o->buildFullAuthorizationUri(); } + /** + * @group oauth2-authorization-uri + */ public function testCannotHaveRelativeRedirectUri() { $this->expectException(InvalidArgumentException::class); @@ -104,6 +156,9 @@ public function testCannotHaveRelativeRedirectUri() $o->buildFullAuthorizationUri(); } + /** + * @group oauth2-authorization-uri + */ public function testAudOrScopeIsRequiredForJwt() { $this->expectException(DomainException::class); @@ -115,6 +170,9 @@ public function testAudOrScopeIsRequiredForJwt() $o->toJwt(); } + /** + * @group oauth2-authorization-uri + */ public function testHasDefaultXXXTypeParams() { $o = new OAuth2($this->minimal); @@ -123,6 +181,9 @@ public function testHasDefaultXXXTypeParams() $this->assertEquals('offline', $q['access_type']); } + /** + * @group oauth2-authorization-uri + */ public function testCanBeUrlObject() { $config = array_merge($this->minimal, [ @@ -132,6 +193,9 @@ public function testCanBeUrlObject() $this->assertEquals('/uri', $o->buildFullAuthorizationUri()->getPath()); } + /** + * @group oauth2-authorization-uri + */ public function testCanOverrideParams() { $overrides = [ @@ -151,6 +215,9 @@ public function testCanOverrideParams() $this->assertEquals('o_state', $q['state']); } + /** + * @group oauth2-authorization-uri + */ public function testAuthorizationUriWithCodeVerifier() { $codeVerifier = 'my_code_verifier'; @@ -175,6 +242,9 @@ public function testAuthorizationUriWithCodeVerifier() $this->assertEquals('S256', $q['code_challenge_method']); } + /** + * @group oauth2-authorization-uri + */ public function testGenerateCodeVerifier() { $o = new OAuth2($this->minimal); @@ -188,6 +258,9 @@ public function testGenerateCodeVerifier() $this->assertNotEquals($codeVerifier, $o->getCodeVerifier()); } + /** + * @group oauth2-authorization-uri + */ public function testIncludesTheScope() { $with_strings = array_merge($this->minimal, ['scope' => 'scope1 scope2']); @@ -203,6 +276,9 @@ public function testIncludesTheScope() $this->assertEquals('scope1 scope2', $q['scope']); } + /** + * @group oauth2-authorization-uri + */ public function testRedirectUriPostmessageIsAllowed() { $o = new OAuth2([ @@ -217,22 +293,19 @@ public function testRedirectUriPostmessageIsAllowed() $this->assertArrayHasKey('redirect_uri', $query); $this->assertEquals('postmessage', $query['redirect_uri']); } -} - -class OAuth2GrantTypeTest extends TestCase -{ - private $minimal = [ - 'authorizationUri' => 'https://accounts.test.org/insecure/url', - 'redirectUri' => 'https://accounts.test.org/redirect/url', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-grant-type + */ public function testReturnsNullIfCannotBeInferred() { $o = new OAuth2($this->minimal); $this->assertNull($o->getGrantType()); } + /** + * @group oauth2-grant-type + */ public function testInfersAuthorizationCode() { $o = new OAuth2($this->minimal); @@ -240,6 +313,9 @@ public function testInfersAuthorizationCode() $this->assertEquals('authorization_code', $o->getGrantType()); } + /** + * @group oauth2-grant-type + */ public function testInfersRefreshToken() { $o = new OAuth2($this->minimal); @@ -247,6 +323,9 @@ public function testInfersRefreshToken() $this->assertEquals('refresh_token', $o->getGrantType()); } + /** + * @group oauth2-grant-type + */ public function testInfersPassword() { $o = new OAuth2($this->minimal); @@ -255,6 +334,9 @@ public function testInfersPassword() $this->assertEquals('password', $o->getGrantType()); } + /** + * @group oauth2-grant-type + */ public function testInfersJwtBearer() { $o = new OAuth2($this->minimal); @@ -266,6 +348,9 @@ public function testInfersJwtBearer() ); } + /** + * @group oauth2-grant-type + */ public function testSetsKnownTypes() { $o = new OAuth2($this->minimal); @@ -275,26 +360,28 @@ public function testSetsKnownTypes() } } + /** + * @group oauth2-grant-type + */ public function testSetsUrlAsGrantType() { $o = new OAuth2($this->minimal); $o->setGrantType('http://a/grant/url'); $this->assertEquals('http://a/grant/url', $o->getGrantType()); } -} - -class OAuth2GetCacheKeyTest extends TestCase -{ - private $minimal = [ - 'clientID' => 'aClientID', - ]; + /** + * @group oauth2-cache-key + */ public function testIsNullWithNoScopesOrAudience() { $o = new OAuth2($this->minimal); $this->assertNull($o->getCacheKey()); } + /** + * @group oauth2-cache-key + */ public function testIsScopeIfSingleScope() { $o = new OAuth2($this->minimal); @@ -302,6 +389,9 @@ public function testIsScopeIfSingleScope() $this->assertEquals('test/scope/1', $o->getCacheKey()); } + /** + * @group oauth2-cache-key + */ public function testIsAllScopesWhenScopeIsArray() { $o = new OAuth2($this->minimal); @@ -309,6 +399,9 @@ public function testIsAllScopesWhenScopeIsArray() $this->assertEquals('test/scope/1:test/scope/2', $o->getCacheKey()); } + /** + * @group oauth2-cache-key + */ public function testIsAudienceWhenScopeIsNull() { $aud = 'https://drive.googleapis.com'; @@ -316,34 +409,37 @@ public function testIsAudienceWhenScopeIsNull() $o->setAudience($aud); $this->assertEquals($aud, $o->getCacheKey()); } -} - -class OAuth2TimingTest extends TestCase -{ - private $minimal = [ - 'authorizationUri' => 'https://accounts.test.org/insecure/url', - 'redirectUri' => 'https://accounts.test.org/redirect/url', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-timing + */ public function testIssuedAtDefaultsToNull() { $o = new OAuth2($this->minimal); $this->assertNull($o->getIssuedAt()); } + /** + * @group oauth2-timing + */ public function testExpiresAtDefaultsToNull() { $o = new OAuth2($this->minimal); $this->assertNull($o->getExpiresAt()); } + /** + * @group oauth2-timing + */ public function testExpiresInDefaultsToNull() { $o = new OAuth2($this->minimal); $this->assertNull($o->getExpiresIn()); } + /** + * @group oauth2-timing + */ public function testSettingExpiresInSetsIssuedAt() { $o = new OAuth2($this->minimal); @@ -354,6 +450,9 @@ public function testSettingExpiresInSetsIssuedAt() $this->assertNotNull($o->getIssuedAt()); } + /** + * @group oauth2-timing + */ public function testSettingExpiresInSetsExpireAt() { $o = new OAuth2($this->minimal); @@ -364,28 +463,28 @@ public function testSettingExpiresInSetsExpireAt() $this->assertEquals($aShortWhile, $o->getExpiresAt() - $o->getIssuedAt()); } + /** + * @group oauth2-timing + */ public function testIsNotExpiredByDefault() { $o = new OAuth2($this->minimal); $this->assertFalse($o->isExpired()); } + /** + * @group oauth2-timing + */ public function testIsNotExpiredIfExpiresAtIsOld() { $o = new OAuth2($this->minimal); $o->setExpiresAt(time() - 2); $this->assertTrue($o->isExpired()); } -} - -class OAuth2GeneralTest extends TestCase -{ - private $minimal = [ - 'authorizationUri' => 'https://accounts.test.org/insecure/url', - 'redirectUri' => 'https://accounts.test.org/redirect/url', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-general + */ public function testFailsOnUnknownSigningAlgorithm() { $this->expectException(InvalidArgumentException::class); @@ -394,6 +493,9 @@ public function testFailsOnUnknownSigningAlgorithm() $o->setSigningAlgorithm('this is definitely not an algorithm name'); } + /** + * @group oauth2-general + */ public function testAllowsKnownSigningAlgorithms() { $o = new OAuth2($this->minimal); @@ -403,6 +505,9 @@ public function testAllowsKnownSigningAlgorithms() } } + /** + * @group oauth2-general + */ public function testFailsOnRelativeRedirectUri() { $this->expectException(InvalidArgumentException::class); @@ -411,6 +516,9 @@ public function testFailsOnRelativeRedirectUri() $o->setRedirectUri('/relative/url'); } + /** + * @group oauth2-general + */ public function testAllowsUrnRedirectUri() { $urn = 'urn:ietf:wg:oauth:2.0:oob'; @@ -418,19 +526,10 @@ public function testAllowsUrnRedirectUri() $o->setRedirectUri($urn); $this->assertEquals($urn, $o->getRedirectUri()); } -} - -class OAuth2JwtTest extends TestCase -{ - private $signingMinimal = [ - 'signingKey' => 'example_key', - 'signingAlgorithm' => 'HS256', - 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', - 'issuer' => 'app@example.com', - 'audience' => 'accounts.google.com', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-jwt + */ public function testFailsWithMissingAudience() { $this->expectException(DomainException::class); @@ -441,6 +540,9 @@ public function testFailsWithMissingAudience() $o->toJwt(); } + /** + * @group oauth2-jwt + */ public function testFailsWithMissingIssuer() { $this->expectException(DomainException::class); @@ -450,6 +552,9 @@ public function testFailsWithMissingIssuer() $o->toJwt(); } + /** + * @group oauth2-jwt + */ public function testCanHaveNoScope() { $testConfig = $this->signingMinimal; @@ -459,6 +564,9 @@ public function testCanHaveNoScope() $this->assertTrue(is_string($jwt)); } + /** + * @group oauth2-jwt + */ public function testFailsWithMissingSigningKey() { $this->expectException(DomainException::class); @@ -469,6 +577,9 @@ public function testFailsWithMissingSigningKey() $o->toJwt(); } + /** + * @group oauth2-jwt + */ public function testFailsWithMissingSigningAlgorithm() { $this->expectException(DomainException::class); @@ -478,6 +589,9 @@ public function testFailsWithMissingSigningAlgorithm() $o->toJwt(); } + /** + * @group oauth2-jwt + */ public function testCanHS256EncodeAValidPayloadWithSigningKeyId() { $testConfig = $this->signingMinimal; @@ -495,6 +609,9 @@ public function testCanHS256EncodeAValidPayloadWithSigningKeyId() $this->assertEquals($roundTrip->scope, $testConfig['scope']); } + /** + * @group oauth2-jwt + */ public function testFailDecodeWithoutSigningKeyId() { $testConfig = $this->signingMinimal; @@ -519,6 +636,9 @@ public function testFailDecodeWithoutSigningKeyId() $this->fail('Expected exception about problem with decode'); } + /** + * @group oauth2-jwt + */ public function testCanHS256EncodeAValidPayload() { $testConfig = $this->signingMinimal; @@ -530,6 +650,9 @@ public function testCanHS256EncodeAValidPayload() $this->assertEquals($roundTrip->scope, $testConfig['scope']); } + /** + * @group oauth2-jwt + */ public function testCanRS256EncodeAValidPayload() { $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); @@ -545,6 +668,9 @@ public function testCanRS256EncodeAValidPayload() $this->assertEquals($roundTrip->scope, $testConfig['scope']); } + /** + * @group oauth2-jwt + */ public function testCanHaveAdditionalClaims() { $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); @@ -559,18 +685,10 @@ public function testCanHaveAdditionalClaims() $roundTrip = JWT::decode($payload, new Key($publicKey, 'RS256')); $this->assertEquals($roundTrip->target_audience, $targetAud); } -} - -class OAuth2GenerateAccessTokenRequestTest extends TestCase -{ - private $tokenRequestMinimal = [ - 'tokenCredentialUri' => 'https://tokens_r_us/test', - 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', - 'issuer' => 'app@example.com', - 'audience' => 'accounts.google.com', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-generate-access-token + */ public function testFailsIfNoTokenCredentialUri() { $this->expectException(DomainException::class); @@ -580,6 +698,9 @@ public function testFailsIfNoTokenCredentialUri() $o->generateCredentialsRequest(); } + /** + * @group oauth2-generate-access-token + */ public function testFailsIfAuthorizationCodeIsMissing() { $this->expectException(DomainException::class); @@ -589,6 +710,9 @@ public function testFailsIfAuthorizationCodeIsMissing() $o->generateCredentialsRequest(); } + /** + * @group oauth2-generate-access-token + */ public function testGeneratesAuthorizationCodeRequests() { $testConfig = $this->tokenRequestMinimal; @@ -605,6 +729,9 @@ public function testGeneratesAuthorizationCodeRequests() $this->assertEquals('an_auth_code', $fields['code']); } + /** + * @group oauth2-generate-access-token + */ public function testGeneratesPasswordRequests() { $testConfig = $this->tokenRequestMinimal; @@ -622,6 +749,9 @@ public function testGeneratesPasswordRequests() $this->assertEquals('a_username', $fields['username']); } + /** + * @group oauth2-generate-access-token + */ public function testGeneratesRefreshTokenRequests() { $testConfig = $this->tokenRequestMinimal; @@ -637,6 +767,9 @@ public function testGeneratesRefreshTokenRequests() $this->assertEquals('a_refresh_token', $fields['refresh_token']); } + /** + * @group oauth2-generate-access-token + */ public function testClientSecretAddedIfSetForAuthorizationCodeRequests() { $testConfig = $this->tokenRequestMinimal; @@ -649,6 +782,9 @@ public function testClientSecretAddedIfSetForAuthorizationCodeRequests() $this->assertEquals('a_client_secret', $fields['client_secret']); } + /** + * @group oauth2-generate-access-token + */ public function testClientSecretAddedIfSetForRefreshTokenRequests() { $testConfig = $this->tokenRequestMinimal; @@ -660,6 +796,9 @@ public function testClientSecretAddedIfSetForRefreshTokenRequests() $this->assertEquals('a_client_secret', $fields['client_secret']); } + /** + * @group oauth2-generate-access-token + */ public function testClientSecretAddedIfSetForPasswordRequests() { $testConfig = $this->tokenRequestMinimal; @@ -672,6 +811,9 @@ public function testClientSecretAddedIfSetForPasswordRequests() $this->assertEquals('a_client_secret', $fields['client_secret']); } + /** + * @group oauth2-generate-access-token + */ public function testGeneratesAssertionRequests() { $testConfig = $this->tokenRequestMinimal; @@ -688,6 +830,9 @@ public function testGeneratesAssertionRequests() $this->assertArrayHasKey('assertion', $fields); } + /** + * @group oauth2-generate-access-token + */ public function testGeneratesExtendedRequests() { $testConfig = $this->tokenRequestMinimal; @@ -704,6 +849,9 @@ public function testGeneratesExtendedRequests() $this->assertEquals('urn:my_test_grant_type', $fields['grant_type']); } + /** + * @group oauth2-generate-access-token + */ public function testTokenUriWithCodeVerifier() { $codeVerifier = 'my_code_verifier'; @@ -728,20 +876,10 @@ public function testTokenUriWithCodeVerifier() $this->assertArrayHasKey('code_verifier', $q); $this->assertEquals($codeVerifier, $q['code_verifier']); } -} - -class OAuth2FetchAuthTokenTest extends TestCase -{ - private $fetchAuthTokenMinimal = [ - 'tokenCredentialUri' => 'https://tokens_r_us/test', - 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', - 'signingKey' => 'example_key', - 'signingAlgorithm' => 'HS256', - 'issuer' => 'app@example.com', - 'audience' => 'accounts.google.com', - 'clientId' => 'aClientID', - ]; + /** + * @group oauth2-fetch-auth-token + */ public function testFailsOn400() { $this->expectException(\GuzzleHttp\Exception\ClientException::class); @@ -754,6 +892,9 @@ public function testFailsOn400() $o->fetchAuthToken($httpHandler); } + /** + * @group oauth2-fetch-auth-token + */ public function testFailsOn500() { $this->expectException(\GuzzleHttp\Exception\ServerException::class); @@ -766,6 +907,9 @@ public function testFailsOn500() $o->fetchAuthToken($httpHandler); } + /** + * @group oauth2-fetch-auth-token + */ public function testFailsOnNoContentTypeIfResponseIsNotJSON() { $this->expectException(\Exception::class); @@ -780,6 +924,9 @@ public function testFailsOnNoContentTypeIfResponseIsNotJSON() $o->fetchAuthToken($httpHandler); } + /** + * @group oauth2-fetch-auth-token + */ public function testFetchesJsonResponseOnNoContentTypeOK() { $testConfig = $this->fetchAuthTokenMinimal; @@ -792,6 +939,9 @@ public function testFetchesJsonResponseOnNoContentTypeOK() $this->assertEquals($tokens['foo'], 'bar'); } + /** + * @group oauth2-fetch-auth-token + */ public function testFetchesFromFormEncodedResponseOK() { $testConfig = $this->fetchAuthTokenMinimal; @@ -809,6 +959,9 @@ public function testFetchesFromFormEncodedResponseOK() $this->assertEquals($tokens['spice'], 'nice'); } + /** + * @group oauth2-fetch-auth-token + */ public function testUpdatesTokenFieldsOnFetch() { $testConfig = $this->fetchAuthTokenMinimal; @@ -842,6 +995,9 @@ public function testUpdatesTokenFieldsOnFetch() $this->assertEquals('scope1 scope2', $o->getGrantedScope()); } + /** + * @group oauth2-fetch-auth-token + */ public function testUpdatesTokenFieldsOnFetchMissingRefreshToken() { $testConfig = $this->fetchAuthTokenMinimal; @@ -875,6 +1031,7 @@ public function testUpdatesTokenFieldsOnFetchMissingRefreshToken() /** * @dataProvider provideGetLastReceivedToken + * @group oauth2-fetch-auth-token */ public function testGetLastReceivedToken( $updateToken, @@ -944,41 +1101,31 @@ public function provideGetLastReceivedToken() ], ]; } -} - -class OAuth2VerifyIdTokenTest extends TestCase -{ - private $publicKey; - private $privateKey; - private $verifyIdTokenMinimal = [ - 'scope' => 'https://www.googleapis.com/auth/userinfo.profile', - 'audience' => 'myaccount.on.host.issuer.com', - 'issuer' => 'an.issuer.com', - 'clientId' => 'myaccount.on.host.issuer.com', - ]; - - public function setUp(): void - { - $this->publicKey = - file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); - $this->privateKey = - file_get_contents(__DIR__ . '/fixtures' . '/private.pem'); - } + /** + * @group oauth2-verify-id-token + */ public function testFailsIfIdTokenIsInvalid() { $this->expectException(UnexpectedValueException::class); + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); $o->setIdToken($not_a_jwt); - $o->verifyIdToken($this->publicKey, ['RS256']); + $o->verifyIdToken($publicKey, ['RS256']); } + /** + * @group oauth2-verify-id-token + */ public function testFailsIfAudienceIsMissing() { $this->expectException(DomainException::class); + + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); + $privateKey = file_get_contents(__DIR__ . '/fixtures' . '/private.pem'); $testConfig = $this->verifyIdTokenMinimal; $now = time(); $origIdToken = [ @@ -987,14 +1134,20 @@ public function testFailsIfAudienceIsMissing() 'iat' => $now, ]; $o = new OAuth2($testConfig); - $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, 'RS256'); + $jwtIdToken = JWT::encode($origIdToken, $privateKey, 'RS256'); $o->setIdToken($jwtIdToken); - $o->verifyIdToken($this->publicKey, ['RS256']); + $o->verifyIdToken($publicKey, ['RS256']); } + /** + * @group oauth2-verify-id-token + */ public function testFailsIfAudienceIsWrong() { $this->expectException(DomainException::class); + + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); + $privateKey = file_get_contents(__DIR__ . '/fixtures' . '/private.pem'); $now = time(); $testConfig = $this->verifyIdTokenMinimal; $origIdToken = [ @@ -1004,64 +1157,85 @@ public function testFailsIfAudienceIsWrong() 'iat' => $now, ]; $o = new OAuth2($testConfig); - $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, 'RS256'); + $jwtIdToken = JWT::encode($origIdToken, $privateKey, 'RS256'); $o->setIdToken($jwtIdToken); - $o->verifyIdToken($this->publicKey, ['RS256']); + $o->verifyIdToken($publicKey, ['RS256']); } + /** + * @group oauth2-verify-id-token + */ public function testFailsWithStringPublicKeyAndAllowedAlgsGreaterThanOne() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('To have multiple allowed algorithms'); + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); $o->setIdToken($not_a_jwt); - $o->verifyIdToken($this->publicKey, ['RS256', 'ES256']); + $o->verifyIdToken($publicKey, ['RS256', 'ES256']); } + /** + * @group oauth2-verify-id-token + */ public function testFailsWithStringPublicKeyAndNoAllowedAlgs() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('When allowed algorithms is empty'); + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); $o->setIdToken($not_a_jwt); - $o->verifyIdToken($this->publicKey, []); + $o->verifyIdToken($publicKey, []); } + /** + * @group oauth2-verify-id-token + */ public function testFailsWithStringInPublicKeyArrayAndNoAllowedAlgs() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('When allowed algorithms is empty'); + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); $o->setIdToken($not_a_jwt); $o->verifyIdToken([ - new Key($this->publicKey, 'RS256'), - $this->publicKey, + new Key($publicKey, 'RS256'), + $publicKey, ], []); } + /** + * @group oauth2-verify-id-token + */ public function testFailsWithInvalidTypeForAllowedAlgs() { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('allowed algorithms must be a string or array'); + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); $testConfig = $this->verifyIdTokenMinimal; $not_a_jwt = 'not a jot'; $o = new OAuth2($testConfig); $o->setIdToken($not_a_jwt); - $o->verifyIdToken($this->publicKey, 123); + $o->verifyIdToken($publicKey, 123); } + /** + * @group oauth2-verify-id-token + */ public function testShouldReturnAValidIdToken() { + $publicKey = file_get_contents(__DIR__ . '/fixtures' . '/public.pem'); + $privateKey = file_get_contents(__DIR__ . '/fixtures' . '/private.pem'); $testConfig = $this->verifyIdTokenMinimal; $now = time(); $origIdToken = [ @@ -1072,9 +1246,9 @@ public function testShouldReturnAValidIdToken() ]; $o = new OAuth2($testConfig); $alg = 'RS256'; - $jwtIdToken = JWT::encode($origIdToken, $this->privateKey, $alg); + $jwtIdToken = JWT::encode($origIdToken, $privateKey, $alg); $o->setIdToken($jwtIdToken); - $roundTrip = $o->verifyIdToken($this->publicKey, [$alg]); + $roundTrip = $o->verifyIdToken($publicKey, [$alg]); $this->assertEquals($origIdToken['aud'], $roundTrip->aud); } }