From 6fae8d187f8621a40e70fe373de7a9a39333873c Mon Sep 17 00:00:00 2001 From: Marko Ivancic Date: Tue, 14 Jan 2025 11:39:31 +0100 Subject: [PATCH] Add coverage --- src/Federation/MetadataPolicyApplicator.php | 11 +- .../MetadataPolicyApplicatorTest.php | 422 ++++++++++++++++++ 2 files changed, 431 insertions(+), 2 deletions(-) create mode 100644 tests/src/Federation/MetadataPolicyApplicatorTest.php diff --git a/src/Federation/MetadataPolicyApplicator.php b/src/Federation/MetadataPolicyApplicator.php index 2de5e9d..ccd6f0f 100644 --- a/src/Federation/MetadataPolicyApplicator.php +++ b/src/Federation/MetadataPolicyApplicator.php @@ -16,15 +16,22 @@ public function __construct( ) { } + /** + * @param array $resolvedMetadataPolicy Resolved (validated) metadata policy. + * @param array $metadata + * @return array + * @throws \SimpleSAML\OpenID\Exceptions\MetadataPolicyException + * @throws \SimpleSAML\OpenID\Exceptions\OpenIdException + */ public function for( - array $metadataPolicy, + array $resolvedMetadataPolicy, array $metadata, ): array { /** * @var string $policyParameterName * @var array $policyOperations */ - foreach ($metadataPolicy as $policyParameterName => $policyOperations) { + foreach ($resolvedMetadataPolicy as $policyParameterName => $policyOperations) { foreach (MetadataPolicyOperatorsEnum::cases() as $metadataPolicyOperatorEnum) { if (!array_key_exists($metadataPolicyOperatorEnum->value, $policyOperations)) { continue; diff --git a/tests/src/Federation/MetadataPolicyApplicatorTest.php b/tests/src/Federation/MetadataPolicyApplicatorTest.php new file mode 100644 index 0000000..d0ab254 --- /dev/null +++ b/tests/src/Federation/MetadataPolicyApplicatorTest.php @@ -0,0 +1,422 @@ + [ + 'default' => [ + 0 => 'authorization_code', + ], + 'superset_of' => [ + 0 => 'authorization_code', + ], + 'subset_of' => [ + 0 => 'authorization_code', + ], + ], + 'token_endpoint_auth_method' => [ + 'one_of' => [ + 0 => 'self_signed_tls_client_auth', + ], + 'essential' => true, + ], + 'token_endpoint_auth_signing_alg' => [ + 'one_of' => [ + 0 => 'PS256', + 1 => 'ES256', + ], + ], + 'subject_type' => [ + 'value' => 'pairwise', + ], + 'contacts' => [ + 'add' => [ + 0 => 'helpdesk@federation.example.org', + 1 => 'helpdesk@org.example.org', + ], + ], + ]; + protected array $metadataSample = [ + 'redirect_uris' => [ + 0 => 'https://rp.example.org/callback', + ], + 'response_types' => [ + 0 => 'code', + ], + 'token_endpoint_auth_method' => 'self_signed_tls_client_auth', + 'sector_identifier_uri' => 'https://org.example.org/sector-ids.json', + 'policy_uri' => 'https://org.example.org/policy.html', + 'contacts' => [ + 0 => 'rp_admins@rp.example.org', + ], + ]; + + protected function sut( + ?Helpers $helpers = null, + ): MetadataPolicyApplicator { + $helpers ??= $this->helpersMock; + + return new MetadataPolicyApplicator($helpers); + } + + protected function setUp(): void + { + $this->helpersMock = $this->createMock(Helpers::class); + } + + public function testCanCreateInstance(): void + { + $this->assertInstanceOf(MetadataPolicyApplicator::class, $this->sut()); + } + + public function testCanApplyBasicMetadataPolicy(): void + { + $expectedResolvedMetadata = [ + 'redirect_uris' => [ + 0 => 'https://rp.example.org/callback', + ], + 'grant_types' => [ + 0 => 'authorization_code', + ], + 'response_types' => [ + 0 => 'code', + ], + 'token_endpoint_auth_method' => 'self_signed_tls_client_auth', + 'subject_type' => 'pairwise', + 'sector_identifier_uri' => 'https://org.example.org/sector-ids.json', + 'policy_uri' => 'https://org.example.org/policy.html', + 'contacts' => [ + 0 => 'rp_admins@rp.example.org', + 1 => 'helpdesk@federation.example.org', + 2 => 'helpdesk@org.example.org', + ], + ]; + + $resolvedMetadata = $this->sut()->for( + $this->metadataPolicySample, + $this->metadataSample, + ); + + $this->assertEquals($expectedResolvedMetadata, $resolvedMetadata); + } + + public function testCanHandleScopeClaims(): void + { + $metadataPolicy = [ + 'scope' => [ + 'superset_of' => [ + 0 => 'openid', + ], + 'add' => [ + 0 => 'email', + ], + ], + ]; + + $metadata = [ + 'scope' => 'openid profile', + ]; + + $this->assertEquals( + ['scope' => 'openid profile email'], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanUnsetMetadataValue(): void + { + $metadataPolicy = [ + 'scope' => [ + 'value' => null, + ], + ]; + + $metadata = [ + 'scope' => 'openid profile', + ]; + + $this->assertEquals( + [], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanAddNonExistingMetadataValue(): void + { + $metadataPolicy = [ + 'scope' => [ + 'add' => 'openid', + ], + ]; + + $metadata = []; + + $this->assertEquals( + ['scope' => 'openid'], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testRemovesParameterOnEmptySubsetOf(): void + { + $metadataPolicy = [ + 'scope' => [ + 'subset_of' => ['openid'], + ], + ]; + $metadata = [ + 'scope' => 'profile', + ]; + + $this->assertEquals( + [], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testHasEmptyParameterOnNonExistingParameterForSubsetOf(): void + { + $metadataPolicy = [ + 'scope' => [ + 'subset_of' => ['openid'], + ], + ]; + $metadata = []; + + $this->assertEquals( + [], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testHasEmptyParameterOnNonExistingParameterForSupersetOf(): void + { + $metadataPolicy = [ + 'scope' => [ + 'superset_of' => ['openid'], + ], + ]; + $metadata = []; + + $this->assertEquals( + [], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testHasEmptyParameterOnNonEssentialParameter(): void + { + $metadataPolicy = [ + 'scope' => [ + 'essential' => false, + ], + ]; + $metadata = []; + + $this->assertEquals( + [], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleValueRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'value' => '1', + ], + ]; + $metadata = [ + 'something' => '2', + ]; + + $this->assertEquals( + ['something' => '1'], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleAddRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'add' => ['2'], + ], + ]; + $metadata = [ + 'something' => ['1'], + ]; + + $this->assertEquals( + ['something' => ['1', '2']], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleDefaultRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'default' => '1', + ], + ]; + $metadata = []; + + $this->assertEquals( + ['something' => '1'], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleOneOfRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'one_of' => ['1', '2'], + ], + ]; + $metadata = [ + 'something' => '1', + ]; + + $this->assertEquals( + ['something' => '1'], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleOneOfBreakRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'one_of' => ['1'], + ], + ]; + $metadata = [ + 'something' => '2', + ]; + + $this->expectException(MetadataPolicyException::class); + $this->expectExceptionMessage('one of'); + + $this->sut()->for($metadataPolicy, $metadata); + } + + public function testCanHandleSubsetOfRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'subset_of' => ['1', '2'], + ], + ]; + $metadata = [ + 'something' => ['1'], + ]; + + $this->assertEquals( + ['something' => ['1']], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleSubsetOfBreakRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'subset_of' => ['1'], + ], + ]; + $metadata = [ + 'something' => ['1', '2'], + ]; + + $this->assertEquals( + ['something' => ['1']], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleSupersetOfRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'superset_of' => ['1'], + ], + ]; + $metadata = [ + 'something' => ['1', '2'], + ]; + + $this->assertEquals( + ['something' => ['1', '2']], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleSupersetOfBreakRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'superset_of' => ['1', '2'], + ], + ]; + $metadata = [ + 'something' => ['1'], + ]; + + $this->expectException(MetadataPolicyException::class); + $this->expectExceptionMessage('superset of'); + + $this->sut()->for($metadataPolicy, $metadata); + } + + public function testCanHandleEssentialRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'essential' => true, + ], + ]; + $metadata = [ + 'something' => ['1', '2'], + ]; + + $this->assertEquals( + ['something' => ['1', '2']], + $this->sut()->for($metadataPolicy, $metadata), + ); + } + + public function testCanHandleEssentialBreakRule(): void + { + $metadataPolicy = [ + 'something' => [ + 'essential' => true, + ], + ]; + $metadata = []; + + + $this->expectException(MetadataPolicyException::class); + $this->expectExceptionMessage('essential'); + + $this->sut()->for($metadataPolicy, $metadata); + } +}