Passed
Push — master ( 045039...d7835c )
by Tim
02:26
created

IDPSSODescriptor   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 376
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 113
dl 0
loc 376
rs 10
c 0
b 0
f 0
wmc 26

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 42 1
A getSupportedAttributes() 0 3 1
A setWantAuthnRequestsSigned() 0 3 1
A setAssertionIDRequestService() 0 8 1
A setAttributeProfiles() 0 4 1
A getSingleSignOnServices() 0 3 1
A getAttributeProfiles() 0 3 1
A getAssertionIDRequestServices() 0 3 1
A getNameIDMappingServices() 0 3 1
A setSingleSignOnServices() 0 9 1
A setNameIDMappingServices() 0 8 1
A wantAuthnRequestsSigned() 0 3 1
A setSupportedAttributes() 0 8 1
B fromXML() 0 58 5
B toUnsignedXML() 0 29 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\XML\saml\Attribute;
10
use SimpleSAML\XML\Exception\InvalidDOMElementException;
11
use SimpleSAML\XML\Exception\TooManyElementsException;
12
use SimpleSAML\XML\Utils as XMLUtils;
13
use SimpleSAML\XMLSecurity\XML\ds\Signature;
14
15
use function preg_split;
16
17
/**
18
 * Class representing SAML 2 IDPSSODescriptor.
19
 *
20
 * @package simplesamlphp/saml2
21
 */
22
final class IDPSSODescriptor extends AbstractSSODescriptor
23
{
24
    /**
25
     * Whether AuthnRequests sent to this IdP should be signed.
26
     *
27
     * @var bool|null
28
     */
29
    protected ?bool $wantAuthnRequestsSigned = null;
30
31
    /**
32
     * List of SingleSignOnService endpoints.
33
     *
34
     * @var \SimpleSAML\SAML2\XML\md\SingleSignOnService[]
35
     */
36
    protected array $ssoServiceEndpoints = [];
37
38
    /**
39
     * List of NameIDMappingService endpoints.
40
     *
41
     * @var \SimpleSAML\SAML2\XML\md\NameIDMappingService[]
42
     */
43
    protected array $nameIDMappingServiceEndpoints = [];
44
45
    /**
46
     * List of AssertionIDRequestService endpoints.
47
     *
48
     * @var \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[]
49
     */
50
    protected array $assertionIDRequestServiceEndpoints = [];
51
52
    /**
53
     * List of supported attribute profiles.
54
     *
55
     * @var \SimpleSAML\SAML2\XML\md\AttributeProfile[]
56
     */
57
    protected array $attributeProfiles = [];
58
59
    /**
60
     * List of supported attributes.
61
     *
62
     * @var \SimpleSAML\SAML2\XML\saml\Attribute[]
63
     */
64
    protected array $attributes = [];
65
66
67
    /**
68
     * IDPSSODescriptor constructor.
69
     *
70
     * @param \SimpleSAML\SAML2\XML\md\SingleSignOnService[] $ssoServiceEndpoints
71
     * @param string[] $protocolSupportEnumeration
72
     * @param bool|null $wantAuthnRequestsSigned
73
     * @param \SimpleSAML\SAML2\XML\md\NameIDMappingService[] $nameIDMappingServiceEndpoints
74
     * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestServiceEndpoints
75
     * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfiles
76
     * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes
77
     * @param string|null $ID
78
     * @param int|null $validUntil
79
     * @param string|null $cacheDuration
80
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
81
     * @param string|null $errorURL
82
     * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors
83
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
84
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts
85
     * @param \SimpleSAML\SAML2\XML\md\ArtifactResolutionService[] $artifactResolutionService
86
     * @param \SimpleSAML\SAML2\XML\md\SingleLogoutService[] $singleLogoutService
87
     * @param \SimpleSAML\SAML2\XML\md\ManageNameIDService[] $manageNameIDService
88
     * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormat
89
     */
90
    public function __construct(
91
        array $ssoServiceEndpoints,
92
        array $protocolSupportEnumeration,
93
        ?bool $wantAuthnRequestsSigned = null,
94
        array $nameIDMappingServiceEndpoints = [],
95
        array $assertionIDRequestServiceEndpoints = [],
96
        array $attributeProfiles = [],
97
        array $attributes = [],
98
        ?string $ID = null,
99
        ?int $validUntil = null,
100
        ?string $cacheDuration = null,
101
        ?Extensions $extensions = null,
102
        ?string $errorURL = null,
103
        array $keyDescriptors = [],
104
        ?Organization $organization = null,
105
        array $contacts = [],
106
        array $artifactResolutionService = [],
107
        array $singleLogoutService = [],
108
        array $manageNameIDService = [],
109
        array $nameIDFormat = []
110
    ) {
111
        parent::__construct(
112
            $protocolSupportEnumeration,
113
            $ID,
114
            $validUntil,
115
            $cacheDuration,
116
            $extensions,
117
            $errorURL,
118
            $keyDescriptors,
119
            $organization,
120
            $contacts,
121
            $artifactResolutionService,
122
            $singleLogoutService,
123
            $manageNameIDService,
124
            $nameIDFormat
125
        );
126
        $this->setSingleSignOnServices($ssoServiceEndpoints);
127
        $this->setWantAuthnRequestsSigned($wantAuthnRequestsSigned);
128
        $this->setNameIDMappingServices($nameIDMappingServiceEndpoints);
129
        $this->setAssertionIDRequestService($assertionIDRequestServiceEndpoints);
130
        $this->setAttributeProfiles($attributeProfiles);
131
        $this->setSupportedAttributes($attributes);
132
    }
133
134
135
    /**
136
     * Collect the value of the WantAuthnRequestsSigned-property
137
     *
138
     * @return bool|null
139
     */
140
    public function wantAuthnRequestsSigned(): ?bool
141
    {
142
        return $this->wantAuthnRequestsSigned;
143
    }
144
145
146
    /**
147
     * Set the value of the WantAuthnRequestsSigned-property
148
     *
149
     * @param bool|null $flag
150
     */
151
    protected function setWantAuthnRequestsSigned(?bool $flag = null): void
152
    {
153
        $this->wantAuthnRequestsSigned = $flag;
154
    }
155
156
157
    /**
158
     * Get the SingleSignOnService endpoints
159
     *
160
     * @return \SimpleSAML\SAML2\XML\md\SingleSignOnService[]
161
     */
162
    public function getSingleSignOnServices(): array
163
    {
164
        return $this->ssoServiceEndpoints;
165
    }
166
167
168
    /**
169
     * Set the SingleSignOnService endpoints
170
     *
171
     * @param \SimpleSAML\SAML2\XML\md\SingleSignOnService[] $singleSignOnServices
172
     */
173
    protected function setSingleSignOnServices(array $singleSignOnServices): void
174
    {
175
        Assert::minCount($singleSignOnServices, 1, 'At least one SingleSignOnService must be specified.');
176
        Assert::allIsInstanceOf(
177
            $singleSignOnServices,
178
            SingleSignOnService::class,
179
            'All md:SingleSignOnService endpoints must be an instance of SingleSignOnService.'
180
        );
181
        $this->ssoServiceEndpoints = $singleSignOnServices;
182
    }
183
184
185
    /**
186
     * Get the NameIDMappingService endpoints
187
     *
188
     * @return \SimpleSAML\SAML2\XML\md\NameIDMappingService[]
189
     */
190
    public function getNameIDMappingServices(): array
191
    {
192
        return $this->nameIDMappingServiceEndpoints;
193
    }
194
195
196
    /**
197
     * Set the NameIDMappingService endpoints
198
     *
199
     * @param \SimpleSAML\SAML2\XML\md\NameIDMappingService[] $nameIDMappingServices
200
     */
201
    protected function setNameIDMappingServices(array $nameIDMappingServices): void
202
    {
203
        Assert::allIsInstanceOf(
204
            $nameIDMappingServices,
205
            NameIDMappingService::class,
206
            'All md:NameIDMappingService endpoints must be an instance of NameIDMappingService.'
207
        );
208
        $this->nameIDMappingServiceEndpoints = $nameIDMappingServices;
209
    }
210
211
212
    /**
213
     * Collect the AssertionIDRequestService endpoints
214
     *
215
     * @return \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[]
216
     */
217
    public function getAssertionIDRequestServices(): array
218
    {
219
        return $this->assertionIDRequestServiceEndpoints;
220
    }
221
222
223
    /**
224
     * Set the AssertionIDRequestService endpoints
225
     *
226
     * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestServices
227
     */
228
    protected function setAssertionIDRequestService(array $assertionIDRequestServices): void
229
    {
230
        Assert::allIsInstanceOf(
231
            $assertionIDRequestServices,
232
            AssertionIDRequestService::class,
233
            'All md:AssertionIDRequestService endpoints must be an instance of AssertionIDRequestService.'
234
        );
235
        $this->assertionIDRequestServiceEndpoints = $assertionIDRequestServices;
236
    }
237
238
239
    /**
240
     * Get the attribute profiles supported
241
     *
242
     * @return \SimpleSAML\SAML2\XML\md\AttributeProfile[]
243
     */
244
    public function getAttributeProfiles(): array
245
    {
246
        return $this->attributeProfiles;
247
    }
248
249
250
    /**
251
     * Set the attribute profiles supported
252
     *
253
     * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfiles
254
     */
255
    protected function setAttributeProfiles(array $attributeProfiles): void
256
    {
257
        Assert::allIsInstanceOf($attributeProfiles, AttributeProfile::class);
258
        $this->attributeProfiles = $attributeProfiles;
259
    }
260
261
262
    /**
263
     * Get the attributes supported by this IdP
264
     *
265
     * @return \SimpleSAML\SAML2\XML\saml\Attribute[]
266
     */
267
    public function getSupportedAttributes(): array
268
    {
269
        return $this->attributes;
270
    }
271
272
273
    /**
274
     * Set the attributes supported by this IdP
275
     *
276
     * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes
277
     */
278
    protected function setSupportedAttributes(array $attributes): void
279
    {
280
        Assert::allIsInstanceOf(
281
            $attributes,
282
            Attribute::class,
283
            'All md:Attribute elements must be an instance of Attribute.'
284
        );
285
        $this->attributes = $attributes;
286
    }
287
288
289
    /**
290
     * Initialize an IDPSSODescriptor.
291
     *
292
     * @param \DOMElement $xml The XML element we should load.
293
     * @return \SimpleSAML\SAML2\XML\md\IDPSSODescriptor
294
     *
295
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
296
     *   if the qualified name of the supplied element is wrong
297
     * @throws \SimpleSAML\XML\Exception\MissingElementException
298
     *   if one of the mandatory child-elements is missing
299
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
300
     *   if too many child-elements of a type are specified
301
     */
302
    public static function fromXML(DOMElement $xml): static
303
    {
304
        Assert::same($xml->localName, 'IDPSSODescriptor', InvalidDOMElementException::class);
305
        Assert::same($xml->namespaceURI, IDPSSODescriptor::NS, InvalidDOMElementException::class);
306
307
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
308
        $validUntil = self::getAttribute($xml, 'validUntil', null);
309
        $orgs = Organization::getChildrenOfClass($xml);
310
        Assert::maxCount(
311
            $orgs,
312
            1,
313
            'More than one Organization found in this descriptor',
314
            TooManyElementsException::class
315
        );
316
317
        $extensions = Extensions::getChildrenOfClass($xml);
318
        Assert::maxCount(
319
            $extensions,
320
            1,
321
            'Only one md:Extensions element is allowed.',
322
            TooManyElementsException::class
323
        );
324
325
        $signature = Signature::getChildrenOfClass($xml);
326
        Assert::maxCount(
327
            $signature,
328
            1,
329
            'Only one ds:Signature element is allowed.',
330
            TooManyElementsException::class
331
        );
332
333
        $idpssod = new static(
334
            SingleSignOnService::getChildrenOfClass($xml),
335
            preg_split('/[\s]+/', trim($protocols)),
336
            self::getBooleanAttribute($xml, 'WantAuthnRequestsSigned', null),
337
            NameIDMappingService::getChildrenOfClass($xml),
338
            AssertionIDRequestService::getChildrenOfClass($xml),
339
            AttributeProfile::getChildrenOfClass($xml),
340
            Attribute::getChildrenOfClass($xml),
341
            self::getAttribute($xml, 'ID', null),
342
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
343
            self::getAttribute($xml, 'cacheDuration', null),
344
            !empty($extensions) ? $extensions[0] : null,
345
            self::getAttribute($xml, 'errorURL', null),
346
            KeyDescriptor::getChildrenOfClass($xml),
347
            !empty($orgs) ? $orgs[0] : null,
348
            ContactPerson::getChildrenOfClass($xml),
349
            ArtifactResolutionService::getChildrenOfClass($xml),
350
            SingleLogoutService::getChildrenOfClass($xml),
351
            ManageNameIDService::getChildrenOfClass($xml),
352
            NameIDFormat::getChildrenOfClass($xml)
353
        );
354
355
        if (!empty($signature)) {
356
            $idpssod->setSignature($signature[0]);
357
            $idpssod->setXML($xml);
358
        }
359
        return $idpssod;
360
    }
361
362
363
    /**
364
     * Convert this assertion to an unsigned XML document.
365
     * This method does not sign the resulting XML document.
366
     *
367
     * @return \DOMElement The root element of the DOM tree
368
     */
369
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
370
    {
371
        $e = parent::toUnsignedXML($parent);
372
373
        if (is_bool($this->wantAuthnRequestsSigned)) {
374
            $e->setAttribute('WantAuthnRequestsSigned', $this->wantAuthnRequestsSigned ? 'true' : 'false');
375
        }
376
377
        foreach ($this->getSingleSignOnServices() as $ep) {
378
            $ep->toXML($e);
379
        }
380
381
        foreach ($this->getNameIDMappingServices() as $ep) {
382
            $ep->toXML($e);
383
        }
384
385
        foreach ($this->getAssertionIDRequestServices() as $ep) {
386
            $ep->toXML($e);
387
        }
388
389
        foreach ($this->getAttributeProfiles() as $ap) {
390
            $ap->toXML($e);
391
        }
392
393
        foreach ($this->getSupportedAttributes() as $a) {
394
            $a->toXML($e);
395
        }
396
397
        return $e;
398
    }
399
}
400