diff --git a/src/SAML11/XML/saml/AbstractAttributeStatementType.php b/src/SAML11/XML/saml/AbstractAttributeStatementType.php new file mode 100644 index 0000000..0987bcf --- /dev/null +++ b/src/SAML11/XML/saml/AbstractAttributeStatementType.php @@ -0,0 +1,92 @@ + $attribute + */ + public function __construct( + Subject $subject, + protected array $attribute = [], + ) { + Assert::allIsInstanceOf($attribute, Attribute::class, SchemaViolationException::class); + + parent::__construct($subject); + } + + + /** + * Collect the value of the attribute-property + * + * @return array<\SimpleSAML\SAML11\XML\saml\Attribute> + */ + public function getAttributes(): array + { + return $this->attribute; + } + + + /** + * Convert XML into an AttributeStatementType + * + * @param \DOMElement $xml The XML element we should load + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $subject = Subject::getChildrenOfClass($xml); + Assert::minCount($subject, 1, MissingElementException::class); + Assert::maxCount($subject, 1, TooManyElementsException::class); + + return new static( + array_pop($subject), + Attribute::getChildrenOfClass($xml), + ); + } + + + /** + * Convert this AttributeStatementType to XML. + * + * @param \DOMElement $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this AttributeStatementType. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + foreach ($this->getAttributes() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/SAML11/XML/saml/AttributeStatement.php b/src/SAML11/XML/saml/AttributeStatement.php new file mode 100644 index 0000000..928f4ff --- /dev/null +++ b/src/SAML11/XML/saml/AttributeStatement.php @@ -0,0 +1,14 @@ + + + TheNameIDValue + + _Test1 + _Test2 + 2 + + testkey + + MIICxDCCAi2gAwIBAgIUZ9QDx+SBFHednUWDFGm9tyVKrgQwDQYJKoZIhvcNAQELBQAwczElMCMGA1UEAwwcc2VsZnNpZ25lZC5zaW1wbGVzYW1scGhwLm9yZzEZMBcGA1UECgwQU2ltcGxlU0FNTHBocCBIUTERMA8GA1UEBwwISG9ub2x1bHUxDzANBgNVBAgMBkhhd2FpaTELMAkGA1UEBhMCVVMwIBcNMjIxMjAzMTAzNTQwWhgPMjEyMjExMDkxMDM1NDBaMHMxJTAjBgNVBAMMHHNlbGZzaWduZWQuc2ltcGxlc2FtbHBocC5vcmcxGTAXBgNVBAoMEFNpbXBsZVNBTUxwaHAgSFExETAPBgNVBAcMCEhvbm9sdWx1MQ8wDQYDVQQIDAZIYXdhaWkxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDessdFRVDTMQQW3Na81B1CjJV1tmY3nopoIhZrkbDxLa+pv7jGDRcYreyu1DoQxEs06V2nHLoyOPhqJXSFivqtUwVYhR6NYgbNI6RRSsIJCweH0YOdlHna7gULPcLX0Bfbi4odStaFwG9yzDySwSEPtsKxm5pENPjNVGh+jJ+H/QIDAQABo1MwUTAdBgNVHQ4EFgQUvV75t8EoQo2fVa0E9otdtIGK5X0wHwYDVR0jBBgwFoAUvV75t8EoQo2fVa0E9otdtIGK5X0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQANQUeiwPJXkWMXuaDHToEBKcezYGqGEYnGUi9LMjeb+Kln7X8nn5iknlz4k77rWCbSwLPC/WDr0ySYQA+HagaeUaFpoiYFJKS6uFlK1HYWnM3W4PUiGHg1/xeZlMO44wTwybXVo0y9KMhchfB5XNbDdoJcqWYvi6xtmZZNRbxUyw== + /CN=selfsigned.simplesamlphp.org/O=SimpleSAMLphp HQ/L=Honolulu/ST=Hawaii/C=US + + some + + + + + FirstValue + SecondValue + + diff --git a/tests/src/SAML11/XML/saml/AttributeStatementTest.php b/tests/src/SAML11/XML/saml/AttributeStatementTest.php new file mode 100644 index 0000000..6795d97 --- /dev/null +++ b/tests/src/SAML11/XML/saml/AttributeStatementTest.php @@ -0,0 +1,174 @@ +some' + )->documentElement), + ], + 'fed654', + ); + + $sc = new SubjectConfirmation( + [new ConfirmationMethod('_Test1'), new ConfirmationMethod('_Test2')], + $scd, + $keyInfo, + ); + + $nameIdentifier = new NameIdentifier( + 'TheNameIDValue', + 'TheNameQualifier', + 'urn:the:format', + ); + + $subject = new Subject($sc, $nameIdentifier); + + $attribute = new Attribute( + 'TheName', + 'https://example.org/', + [new AttributeValue('FirstValue'), new AttributeValue('SecondValue')] + ); + + $attributeStatement = new AttributeStatement( + $subject, + [$attribute], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($attributeStatement), + ); + } + + + public function testMarshallingElementOrdering(): void + { + $attributeStatement = AttributeStatement::fromXML(self::$xmlRepresentation->documentElement); + $attributeStatementElement = $attributeStatement->toXML(); + + // Test for a Subject + $xpCache = XPath::getXPath($attributeStatementElement); + $attributeStatementElements = XPath::xpQuery( + $attributeStatementElement, + './saml_assertion:Subject', + $xpCache, + ); + $this->assertCount(1, $attributeStatementElements); + + // Test ordering of AttributeStatement contents + /** @psalm-var \DOMElement[] $authnStatementElements */ + $attributeStatementElements = XPath::xpQuery( + $attributeStatementElement, + './saml_assertion:Subject/following-sibling::*', + $xpCache, + ); + $this->assertCount(1, $attributeStatementElements); + $this->assertEquals('saml:Attribute', $attributeStatementElements[0]->tagName); + } +}