Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Test fixtures and README examples use RFC 2606 reserved domains
(`provider.example.org` for IdP-side URLs, `app.example.org` for
application-side URLs) instead of invented registrable domains

- Strengthened constructor tests guided by mutation testing: the `jwt`
collaborator is asserted to become the request factory, and `0` is
asserted to be an accepted boundary value for `cacheDuration` and
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ require_once __DIR__.'/vendor/autoload.php';
use ItkDev\OpenIdConnect\Security\OpenIdConfigurationProvider;

$provider = new OpenIdConfigurationProvider([
'redirectUri' => 'https://some.url', // Absolute url to where the user is redirected after a successful login
'redirectUri' => 'https://app.example.org', // Absolute url to where the user is redirected after a successful login
'openIDConnectMetadataUrl' => 'https:/.../openid-configuration', // url to OpenId Discovery document
'cacheItemPool' => 'Psr6/CacheItemPoolInterface', // Implementation of CacheItemPoolInterface for caching above discovery document
'clientId' => 'client_id', // Client id assigned by authorizer
Expand Down
56 changes: 28 additions & 28 deletions tests/Security/OpenIdConfigurationProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class OpenIdConfigurationProviderTest extends TestCase

private const CLIENT_ID = 'test_client_id';
private const CLIENT_SECRET = 'test_client_secret';
private const REDIRECT_URI = 'https://redirect.url';
private const REDIRECT_URI = 'https://app.example.org';
private const NONCE = '12345678';

private OpenIdConfigurationProvider $provider;
Expand All @@ -44,7 +44,7 @@ public function setUp(): void
{
parent::setUp();

$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -106,7 +106,7 @@ public function testConstructCacheDuration(): void

$provider = new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
'cacheDuration' => -10,
], []);
}
Expand All @@ -120,7 +120,7 @@ public function testConstructLeeway(): void

$provider = new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
'leeway' => -10,
], []);
}
Expand All @@ -133,7 +133,7 @@ public function testConstructZeroCacheDurationAndLeewayAccepted(): void
// tolerate no clock skew. Only negative values are rejected.
$provider = new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
'cacheDuration' => 0,
'leeway' => 0,
], []);
Expand All @@ -148,7 +148,7 @@ public function testConstructWiresJwtCollaboratorAsRequestFactory(): void

$provider = new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
], [
'jwt' => $requestFactory,
]);
Expand Down Expand Up @@ -364,11 +364,11 @@ public function testConstructHttpUrlNotAllowed(): void
$mockCacheItemPool = $this->createStub(CacheItemPoolInterface::class);

$this->expectException(IllegalSchemeException::class);
$this->expectExceptionMessage('OpenIDConnectMetadataUrl must use https: http://some.url/openid-configuration');
$this->expectExceptionMessage('OpenIDConnectMetadataUrl must use https: http://provider.example.org/openid-configuration');

new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'http://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'http://provider.example.org/openid-configuration',
], []);
}

Expand All @@ -383,7 +383,7 @@ public function testConstructHttpUrlAllowed(): void

$provider = new OpenIdConfigurationProvider([
'cacheItemPool' => $mockCacheItemPool,
'openIDConnectMetadataUrl' => 'http://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'http://provider.example.org/openid-configuration',
'allowHttp' => true,
'clientId' => self::CLIENT_ID,
'clientSecret' => self::CLIENT_SECRET,
Expand Down Expand Up @@ -518,7 +518,7 @@ public function testValidateIdTokenArrayAudienceInvalid(): void
public function testGetIdTokenSuccess(): void
{
$tokenEndpoint = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/oauth2/v2.0/token?p=test-policy';
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -568,7 +568,7 @@ public function testGetIdTokenSuccess(): void

public function testGetIdTokenFailure(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockHttpClient = $this->createStub(ClientInterface::class);
// PSR-18 transport stub — Guzzle's real exceptions need a RequestInterface
Expand Down Expand Up @@ -608,7 +608,7 @@ public function testGetIdTokenFailure(): void
public function testGetIdTokenRejectsInvalidJsonResponse(): void
{
$tokenEndpoint = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/oauth2/v2.0/token?p=test-policy';
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');

Expand Down Expand Up @@ -663,7 +663,7 @@ public function testGetIdTokenRejectsInvalidJsonResponse(): void
public function testGetIdTokenRejectsResponseWithoutStringIdToken(): void
{
$tokenEndpoint = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/oauth2/v2.0/token?p=test-policy';
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');

Expand Down Expand Up @@ -726,7 +726,7 @@ public function testGetConfigurationCacheHit(): void
$mockHttpClient = $this->createStub(ClientInterface::class);

$provider = new OpenIdConfigurationProvider([
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
'cacheItemPool' => $mockCacheItemPool,
'clientId' => self::CLIENT_ID,
'clientSecret' => self::CLIENT_SECRET,
Expand Down Expand Up @@ -758,7 +758,7 @@ public function testGetConfigurationNonStringValue(): void
$mockCacheItemPool->method('getItem')->willReturn($mockCacheItem);

$provider = new OpenIdConfigurationProvider([
'openIDConnectMetadataUrl' => 'https://some.url/openid-configuration',
'openIDConnectMetadataUrl' => 'https://provider.example.org/openid-configuration',
'cacheItemPool' => $mockCacheItemPool,
'clientId' => self::CLIENT_ID,
'clientSecret' => self::CLIENT_SECRET,
Expand All @@ -776,7 +776,7 @@ public function testGetConfigurationNonStringValue(): void

public function testFetchJsonResourceNon200(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockStream = $this->createStub(StreamInterface::class);
$mockStream->method('getContents')->willReturn('');
Expand Down Expand Up @@ -805,14 +805,14 @@ public function testFetchJsonResourceNon200(): void
]);

$this->expectException(HttpException::class);
$this->expectExceptionMessage('Cannot access json resource: https://some.url/openid-configuration');
$this->expectExceptionMessage('Cannot access json resource: https://provider.example.org/openid-configuration');

$provider->getBaseAuthorizationUrl();
}

public function testFetchJsonResourceClientException(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockHttpClient = $this->createStub(ClientInterface::class);
$exception = new class('Connection refused') extends \RuntimeException implements ClientExceptionInterface {
Expand Down Expand Up @@ -849,7 +849,7 @@ public function testFetchJsonResourceClientException(): void

public function testFetchJsonResourceInvalidJson(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$mockStream = $this->createStub(StreamInterface::class);
$mockStream->method('getContents')->willReturn('not valid json{{{');
Expand Down Expand Up @@ -938,7 +938,7 @@ public function testGetJwtVerificationKeysRejectsRsaWithoutStringExpOrModulus():

public function testGetJwtVerificationKeysRejectsNonStringKid(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -985,7 +985,7 @@ public function testGetJwtVerificationKeysRejectsNonStringKid(): void

public function testGetJwtVerificationKeysUnsupportedKeyType(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -1031,7 +1031,7 @@ public function testGetJwtVerificationKeysUnsupportedKeyType(): void

public function testGetJwtVerificationKeysCacheHit(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$configuration = $this->loadMockFixture('mockOpenIDConfiguration.json');

Expand Down Expand Up @@ -1078,7 +1078,7 @@ public function testGetJwtVerificationKeysCacheHit(): void

public function testGetConfigurationCachesFetchedDocument(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$configuration = $this->loadMockFixture('mockOpenIDConfiguration.json');

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -1115,7 +1115,7 @@ public function testGetConfigurationCachesFetchedDocument(): void

public function testGetJwtVerificationKeysCachesFetchedKeys(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$configuration = $this->loadMockFixture('mockOpenIDConfiguration.json');

$mockKeysResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDValidationKeys.json');
Expand Down Expand Up @@ -1194,7 +1194,7 @@ public function testGetJwtVerificationKeysBuildsAllJwksKeys(): void

public function testGetConfigurationCacheInvalidArgument(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';

$exception = new class('Invalid cache key') extends \InvalidArgumentException implements \Psr\Cache\InvalidArgumentException {
};
Expand Down Expand Up @@ -1227,7 +1227,7 @@ public function testGetConfigurationCacheInvalidArgument(): void

public function testGetJwtVerificationKeysCacheInvalidArgument(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$configuration = $this->loadMockFixture('mockOpenIDConfiguration.json');

$configCacheItem = $this->createStub(CacheItemInterface::class);
Expand Down Expand Up @@ -1272,7 +1272,7 @@ public function testGetJwtVerificationKeysCacheInvalidArgument(): void

public function testBase64urlDecodeFailure(): void
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down Expand Up @@ -1348,7 +1348,7 @@ private function loadMockFixture(string $filename): array
*/
private function createProviderWithCustomJwks(string $jwksJson): OpenIdConfigurationProvider
{
$openIDConnectMetadataUrl = 'https://some.url/openid-configuration';
$openIDConnectMetadataUrl = 'https://provider.example.org/openid-configuration';
$jwks_uri = 'https://azure_b2c_test.b2clogin.com/azure_b2c_test.onmicrosoft.com/discovery/v2.0/keys?p=test-policy';

$mockConfigResponse = $this->getMockHttpSuccessResponse('/../MockData/mockOpenIDConfiguration.json');
Expand Down
Loading