From c00c01215927c3d181ab5ea407c11ce3b6379006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Ivan=C4=8Di=C4=87?= Date: Fri, 14 Aug 2026 16:49:01 +0200 Subject: [PATCH] Type the SecurityTokenService as fed:SecurityTokenServiceType --- src/IdP/MetadataBuilder.php | 9 ++-- tests/src/IdP/MetadataBuilderTest.php | 78 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 tests/src/IdP/MetadataBuilderTest.php diff --git a/src/IdP/MetadataBuilder.php b/src/IdP/MetadataBuilder.php index a7cadcc..ffe6b0b 100644 --- a/src/IdP/MetadataBuilder.php +++ b/src/IdP/MetadataBuilder.php @@ -46,7 +46,6 @@ use SimpleSAML\XMLSchema\Type\Base64BinaryValue; use SimpleSAML\XMLSchema\Type\BooleanValue; use SimpleSAML\XMLSchema\Type\IDValue; -use SimpleSAML\XMLSchema\Type\NCNameValue; use SimpleSAML\XMLSchema\Type\QNameValue; use SimpleSAML\XMLSecurity\Alg\Signature\SignatureAlgorithmFactory; use SimpleSAML\XMLSecurity\Constants as C_XMLSEC; @@ -219,10 +218,12 @@ public function getSecurityTokenService(): SecurityTokenServiceType $defaultEndpoint = Module::getModuleURL('adfs') . '/idp/prp.php'; return new SecurityTokenServiceType( + // The first argument is the xsi:type, not the element's own name. getLocalName()/NS/NS_PREFIX + // describe the element this serialises to — md:RoleDescriptor — so they yield the wrong QName. QNameValue::fromParts( - NCNameValue::fromString(SecurityTokenServiceType::getLocalName()), - AnyURIValue::fromString(SecurityTokenServiceType::NS), - NCNameValue::fromString(SecurityTokenServiceType::NS_PREFIX), + SecurityTokenServiceType::getXsiTypeName(), + SecurityTokenServiceType::getXsiTypeNamespaceURI(), + SecurityTokenServiceType::getXsiTypePrefix(), ), protocolSupportEnumeration: SAMLAnyURIListValue::fromArray( [C_TRUST::NS_TRUST_200512, C_TRUST::NS_TRUST_200502, C_FED::NS_FED], diff --git a/tests/src/IdP/MetadataBuilderTest.php b/tests/src/IdP/MetadataBuilderTest.php new file mode 100644 index 0000000..332fc45 --- /dev/null +++ b/tests/src/IdP/MetadataBuilderTest.php @@ -0,0 +1,78 @@ +config = Configuration::loadFromArray( + [ + 'enable.adfs-idp' => true, + 'module.enable' => ['adfs' => true], + 'metadata.sources' => [ + ['type' => 'flatfile', 'directory' => dirname(__DIR__, 2) . '/metadata'], + ], + ], + '[ARRAY]', + 'simplesaml', + ); + + Configuration::setPreLoadedConfig($this->config, 'config.php'); + } + + + /** + * Test that the SecurityTokenService is typed as fed:SecurityTokenServiceType. + * + * The first constructor argument is the element's xsi:type, not its own name. Building it from + * getLocalName()/NS/NS_PREFIX describes the element this serialises to — md:RoleDescriptor — + * and so publishes a role descriptor that claims to be typed as itself. + */ + public function testSecurityTokenServiceCarriesItsXsiType(): void + { + $metadata = Configuration::loadFromArray( + ['entityid' => 'urn:example:adfs'], + 'adfs-idp-hosted', + ); + + $xsiType = (new MetadataBuilder($this->config, $metadata)) + ->getSecurityTokenService() + ->getXsiType(); + + $this->assertEquals('fed:SecurityTokenServiceType', strval($xsiType)); + $this->assertEquals( + AbstractSecurityTokenServiceType::XSI_TYPE_NAME, + $xsiType->getLocalName()->getValue(), + ); + + // The prefix is lexical; what identifies the type is the namespace it resolves to. + $namespaceURI = $xsiType->getNamespaceURI(); + $this->assertNotNull($namespaceURI); + $this->assertEquals(C_FED::NS_FED, $namespaceURI->getValue()); + } +}