Skip to content

Commit dd33fe3

Browse files
committed
Add AnyURIList-type
1 parent a2e0b87 commit dd33fe3

20 files changed

+242
-122
lines changed

src/Type/AnyURIListValue.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\Type;
6+
7+
use SimpleSAML\SAML2\Assert\Assert;
8+
use SimpleSAML\SAML2\Constants as C;
9+
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
10+
use SimpleSAML\XML\Exception\SchemaViolationException;
11+
use SimpleSAML\XML\Type\ListTypeInterface;
12+
13+
use function array_map;
14+
use function preg_split;
15+
use function str_replace;
16+
use function trim;
17+
18+
/**
19+
* @package simplesaml/saml2
20+
*/
21+
class AnyURIListValue extends SAMLAnyURIValue implements ListTypeInterface
22+
{
23+
/** @var string */
24+
public const SCHEMA_TYPE = 'AnyURIList';
25+
26+
27+
/**
28+
* Validate the value.
29+
*
30+
* @param string $value
31+
* @throws \SimpleSAML\XML\Exception\SchemaViolationException on failure
32+
* @return void
33+
*/
34+
protected function validateValue(string $value): void
35+
{
36+
$uris = preg_split('/[\s]+/', $this->sanitizeValue($value), C::UNBOUNDED_LIMIT);
37+
38+
Assert::allValidAnyURI($uris, SchemaViolationException::class);
39+
}
40+
41+
42+
/**
43+
* Convert an array of xs:anyURI items into a saml:AnyURIList
44+
*
45+
* @param string[] $uris
46+
* @return static
47+
*/
48+
public static function fromArray(array $uris): static
49+
{
50+
$str = '';
51+
foreach ($uris as $uri) {
52+
$str .= str_replace(' ', '+', $uri) . ' ';
53+
}
54+
55+
return new static(trim($str));
56+
}
57+
58+
59+
/**
60+
* Convert this saml:AnyURIList to an array of xs:anyURI items
61+
*
62+
* @return array<\SimpleSAML\SAML2\Type\SAMLAnyURIValue>
63+
*/
64+
public function toArray(): array
65+
{
66+
$uris = preg_split('/[\s]+/', $this->getValue(), C::UNBOUNDED_LIMIT);
67+
$uris = str_replace('+', ' ', $uris);
68+
69+
return array_map([SAMLAnyURIValue::class, 'fromString'], $uris);
70+
}
71+
}

src/XML/md/AbstractRoleDescriptor.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
99
use SimpleSAML\SAML2\Constants as C;
10-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue};
10+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1111
use SimpleSAML\SAML2\Utils;
1212
use SimpleSAML\SAML2\XML\{ExtensionPointInterface, ExtensionPointTrait};
1313
use SimpleSAML\XML\Chunk;
1414
use SimpleSAML\XML\Exception\{InvalidDOMElementException, SchemaViolationException, TooManyElementsException};
1515
use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait};
16-
use SimpleSAML\XML\Type\{DurationValue, IDValue, QNameValue, StringValue};
16+
use SimpleSAML\XML\Type\{DurationValue, IDValue, QNameValue};
1717

1818
use function array_pop;
1919

@@ -37,7 +37,8 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme
3737
* Initialize a md:RoleDescriptor from scratch.
3838
*
3939
* @param \SimpleSAML\XML\Type\QNameValue $type
40-
* @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported.
40+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
41+
* A set of URI specifying the protocols supported.
4142
* @param \SimpleSAML\XML\Type\IDValue|null $ID The ID for this document. Defaults to null.
4243
* @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document.
4344
* Defaults to null.
@@ -56,7 +57,7 @@ abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType impleme
5657
*/
5758
public function __construct(
5859
protected QNameValue $type,
59-
array $protocolSupportEnumeration,
60+
AnyURIListValue $protocolSupportEnumeration,
6061
?IDValue $ID = null,
6162
?SAMLDateTimeValue $validUntil = null,
6263
?DurationValue $cacheDuration = null,
@@ -117,8 +118,6 @@ public static function fromXML(DOMElement $xml): static
117118
$handler = Utils::getContainer()->getExtensionHandler($type);
118119
if ($handler === null) {
119120
// we don't have a handler, proceed with unknown RoleDescriptor
120-
$protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class);
121-
122121
$orgs = Organization::getChildrenOfClass($xml);
123122
Assert::maxCount(
124123
$orgs,
@@ -138,7 +137,7 @@ public static function fromXML(DOMElement $xml): static
138137
return new UnknownRoleDescriptor(
139138
new Chunk($xml),
140139
$type,
141-
preg_split('/[\s]+/', trim($protocols->getValue())),
140+
self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
142141
self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
143142
self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
144143
self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),

src/XML/md/AbstractRoleDescriptorType.php

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66

77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
9-
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
109
use SimpleSAML\SAML2\Constants as C;
11-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue};
12-
use SimpleSAML\XML\Exception\SchemaViolationException;
10+
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
11+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1312
use SimpleSAML\XML\ExtendableAttributesTrait;
1413
use SimpleSAML\XML\Type\{DurationValue, IDValue};
1514
use SimpleSAML\XML\XsNamespace as NS;
1615

17-
use function implode;
16+
use function strval;
1817

1918
/**
2019
* Class representing SAML2 RoleDescriptorType.
@@ -32,7 +31,8 @@ abstract class AbstractRoleDescriptorType extends AbstractMetadataDocument
3231
/**
3332
* Initialize a RoleDescriptor.
3433
*
35-
* @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported.
34+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
35+
* A set of URI specifying the protocols supported.
3636
* @param \SimpleSAML\XML\Type\IDValue|null $ID The ID for this document. Defaults to null.
3737
* @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document.
3838
* Defaults to null.
@@ -50,7 +50,7 @@ abstract class AbstractRoleDescriptorType extends AbstractMetadataDocument
5050
* @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes
5151
*/
5252
public function __construct(
53-
protected array $protocolSupportEnumeration,
53+
protected AnyURIListValue $protocolSupportEnumeration,
5454
?IDValue $ID = null,
5555
?SAMLDateTimeValue $validUntil = null,
5656
?DurationValue $cacheDuration = null,
@@ -61,13 +61,18 @@ public function __construct(
6161
protected array $contact = [],
6262
array $namespacedAttributes = [],
6363
) {
64-
Assert::maxCount($protocolSupportEnumeration, C::UNBOUNDED_LIMIT);
65-
Assert::minCount(
66-
$protocolSupportEnumeration,
67-
1,
68-
'At least one protocol must be supported by this ' . static::NS_PREFIX . ':' . static::getLocalName() . '.',
64+
/**
65+
* A whitespace-delimited set of URIs that identify the set of protocol specifications supported by the
66+
* role element. For SAML V2.0 entities, this set MUST include the SAML protocol namespace URI,
67+
* urn:oasis:names:tc:SAML:2.0:protocol.
68+
*/
69+
Assert::contains(
70+
strval($protocolSupportEnumeration),
71+
C::NS_SAMLP,
72+
'SAML v2.0 entities MUST include the SAML protocol namespace URI in their'
73+
. ' protocolSupportEnumeration attribute',
74+
ProtocolViolationException::class,
6975
);
70-
SAMLAssert::allValidURI($protocolSupportEnumeration, SchemaViolationException::class);
7176
Assert::maxCount($contact, C::UNBOUNDED_LIMIT);
7277
Assert::allIsInstanceOf(
7378
$contact,
@@ -101,9 +106,9 @@ public function getErrorURL(): ?SAMLAnyURIValue
101106
/**
102107
* Collect the value of the protocolSupportEnumeration property.
103108
*
104-
* @return string[]
109+
* @return \SimpleSAML\SAML2\Type\AnyURIListValue
105110
*/
106-
public function getProtocolSupportEnumeration(): array
111+
public function getProtocolSupportEnumeration(): AnyURIListValue
107112
{
108113
return $this->protocolSupportEnumeration;
109114
}
@@ -151,10 +156,10 @@ public function getKeyDescriptor(): array
151156
public function toUnsignedXML(?DOMElement $parent = null): DOMElement
152157
{
153158
$e = parent::toUnsignedXML($parent);
154-
$e->setAttribute('protocolSupportEnumeration', implode(' ', $this->getProtocolSupportEnumeration()));
159+
$e->setAttribute('protocolSupportEnumeration', strval($this->getProtocolSupportEnumeration()));
155160

156161
if ($this->getErrorURL() !== null) {
157-
$e->setAttribute('errorURL', $this->getErrorURL()->getValue());
162+
$e->setAttribute('errorURL', strval($this->getErrorURL()));
158163
}
159164

160165
foreach ($this->getKeyDescriptor() as $kd) {

src/XML/md/AbstractSSODescriptor.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
99
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
10-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue};
10+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1111
use SimpleSAML\XML\Constants as C;
1212
use SimpleSAML\XML\Type\{IDValue, DurationValue};
1313

@@ -21,7 +21,7 @@ abstract class AbstractSSODescriptor extends AbstractRoleDescriptorType
2121
/**
2222
* Initialize a RoleDescriptor.
2323
*
24-
* @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported.
24+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration A set of URI specifying the protocols supported.
2525
* @param \SimpleSAML\XML\Type\IDValue|null $ID The ID for this document. Defaults to null.
2626
* @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validity for this document.
2727
* Defaults to null.
@@ -46,7 +46,7 @@ abstract class AbstractSSODescriptor extends AbstractRoleDescriptorType
4646
* Defaults to an empty array.
4747
*/
4848
public function __construct(
49-
array $protocolSupportEnumeration,
49+
AnyURIListValue $protocolSupportEnumeration,
5050
?IDValue $ID = null,
5151
?SAMLDateTimeValue $validUntil = null,
5252
?DurationValue $cacheDuration = null,

src/XML/md/AttributeAuthorityDescriptor.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
9-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue};
9+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1010
use SimpleSAML\SAML2\XML\saml\Attribute;
1111
use SimpleSAML\XML\Constants as C;
1212
use SimpleSAML\XML\Exception\{InvalidDOMElementException, MissingElementException, TooManyElementsException};
@@ -30,7 +30,7 @@ final class AttributeAuthorityDescriptor extends AbstractRoleDescriptorType impl
3030
* AttributeAuthorityDescriptor constructor.
3131
*
3232
* @param \SimpleSAML\SAML2\XML\md\AttributeService[] $attributeService
33-
* @param string[] $protocolSupportEnumeration
33+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
3434
* @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService
3535
* @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormat
3636
* @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfile
@@ -47,7 +47,7 @@ final class AttributeAuthorityDescriptor extends AbstractRoleDescriptorType impl
4747
*/
4848
public function __construct(
4949
protected array $attributeService,
50-
array $protocolSupportEnumeration,
50+
AnyURIListValue $protocolSupportEnumeration,
5151
protected array $assertionIDRequestService = [],
5252
protected array $nameIDFormat = [],
5353
protected array $attributeProfile = [],
@@ -174,8 +174,6 @@ public static function fromXML(DOMElement $xml): static
174174
Assert::same($xml->localName, 'AttributeAuthorityDescriptor', InvalidDOMElementException::class);
175175
Assert::same($xml->namespaceURI, AttributeAuthorityDescriptor::NS, InvalidDOMElementException::class);
176176

177-
$protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class);
178-
179177
$attrServices = AttributeService::getChildrenOfClass($xml);
180178
Assert::notEmpty(
181179
$attrServices,
@@ -214,7 +212,7 @@ public static function fromXML(DOMElement $xml): static
214212

215213
$authority = new static(
216214
$attrServices,
217-
preg_split('/[\s]+/', $protocols->getValue()),
215+
self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
218216
$assertIDReqServices,
219217
$nameIDFormats,
220218
$attrProfiles,

src/XML/md/AuthnAuthorityDescriptor.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66

77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
9-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue};
9+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1010
use SimpleSAML\XML\Constants as C;
1111
use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException};
1212
use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait};
1313
use SimpleSAML\XML\Type\{DurationValue, IDValue};
1414
use SimpleSAML\XMLSecurity\XML\ds\Signature;
1515

16-
use function preg_split;
17-
1816
/**
1917
* Class representing SAML 2 metadata AuthnAuthorityDescriptor.
2018
*
@@ -28,7 +26,7 @@ final class AuthnAuthorityDescriptor extends AbstractRoleDescriptorType implemen
2826
* AuthnAuthorityDescriptor constructor.
2927
*
3028
* @param array $authnQueryService
31-
* @param array $protocolSupportEnumeration
29+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
3230
* @param array $assertionIDRequestService
3331
* @param array $nameIDFormat
3432
* @param \SimpleSAML\XML\Type\IDValue|null $ID
@@ -43,7 +41,7 @@ final class AuthnAuthorityDescriptor extends AbstractRoleDescriptorType implemen
4341
*/
4442
public function __construct(
4543
protected array $authnQueryService,
46-
array $protocolSupportEnumeration,
44+
AnyURIListValue $protocolSupportEnumeration,
4745
protected array $assertionIDRequestService = [],
4846
protected array $nameIDFormat = [],
4947
?IDValue $ID = null,
@@ -138,8 +136,6 @@ public static function fromXML(DOMElement $xml): static
138136
Assert::same($xml->localName, 'AuthnAuthorityDescriptor', InvalidDOMElementException::class);
139137
Assert::same($xml->namespaceURI, AuthnAuthorityDescriptor::NS, InvalidDOMElementException::class);
140138

141-
$protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
142-
143139
$authnQueryServices = AuthnQueryService::getChildrenOfClass($xml);
144140
$assertionIDRequestServices = AssertionIDRequestService::getChildrenOfClass($xml);
145141
$nameIDFormats = NameIDFormat::getChildrenOfClass($xml);
@@ -170,7 +166,7 @@ public static function fromXML(DOMElement $xml): static
170166

171167
$authority = new static(
172168
$authnQueryServices,
173-
preg_split('/[\s]+/', trim($protocols->getValue())),
169+
self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
174170
$assertionIDRequestServices,
175171
$nameIDFormats,
176172
self::getOptionalAttribute($xml, 'ID', IDValue::class, null),

src/XML/md/IDPSSODescriptor.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DOMElement;
88
use SimpleSAML\SAML2\Assert\Assert;
9-
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue};
9+
use SimpleSAML\SAML2\Type\{AnyURIListValue, SAMLAnyURIValue, SAMLDateTimeValue};
1010
use SimpleSAML\SAML2\XML\saml\Attribute;
1111
use SimpleSAML\XML\Constants as C;
1212
use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException};
@@ -30,7 +30,7 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali
3030
* IDPSSODescriptor constructor.
3131
*
3232
* @param \SimpleSAML\SAML2\XML\md\SingleSignOnService[] $singleSignOnService
33-
* @param string[] $protocolSupportEnumeration
33+
* @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
3434
* @param \SimpleSAML\XML\Type\BooleanValue|null $wantAuthnRequestsSigned
3535
* @param \SimpleSAML\SAML2\XML\md\NameIDMappingService[] $nameIDMappingService
3636
* @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService
@@ -51,7 +51,7 @@ final class IDPSSODescriptor extends AbstractSSODescriptor implements SchemaVali
5151
*/
5252
public function __construct(
5353
protected array $singleSignOnService,
54-
array $protocolSupportEnumeration,
54+
AnyURIListValue $protocolSupportEnumeration,
5555
protected ?BooleanValue $wantAuthnRequestsSigned = null,
5656
protected array $nameIDMappingService = [],
5757
protected array $assertionIDRequestService = [],
@@ -200,8 +200,6 @@ public static function fromXML(DOMElement $xml): static
200200
Assert::same($xml->localName, 'IDPSSODescriptor', InvalidDOMElementException::class);
201201
Assert::same($xml->namespaceURI, IDPSSODescriptor::NS, InvalidDOMElementException::class);
202202

203-
$protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
204-
205203
$orgs = Organization::getChildrenOfClass($xml);
206204
Assert::maxCount(
207205
$orgs,
@@ -228,7 +226,7 @@ public static function fromXML(DOMElement $xml): static
228226

229227
$idpssod = new static(
230228
SingleSignOnService::getChildrenOfClass($xml),
231-
preg_split('/[\s]+/', trim($protocols->getValue())),
229+
self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
232230
self::getOptionalAttribute($xml, 'WantAuthnRequestsSigned', BooleanValue::class, null),
233231
NameIDMappingService::getChildrenOfClass($xml),
234232
AssertionIDRequestService::getChildrenOfClass($xml),

0 commit comments

Comments
 (0)