Passed
Pull Request — master (#374)
by Tim
02:36
created

SPSSODescriptor::getWantAssertionsSigned()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use SimpleSAML\SAML2\Assert\Assert;
9
use SimpleSAML\SAML2\Type\AnyURIListValue;
10
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
11
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
12
use SimpleSAML\XML\Constants as C;
13
use SimpleSAML\XML\SchemaValidatableElementInterface;
14
use SimpleSAML\XML\SchemaValidatableElementTrait;
15
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
16
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
17
use SimpleSAML\XMLSchema\Type\BooleanValue;
18
use SimpleSAML\XMLSchema\Type\DurationValue;
19
use SimpleSAML\XMLSchema\Type\IDValue;
20
use SimpleSAML\XMLSecurity\XML\ds\Signature;
21
22
use function array_filter;
23
use function var_export;
24
25
/**
26
 * Class representing SAML 2 SPSSODescriptor.
27
 *
28
 * @package simplesamlphp/saml2
29
 */
30
final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValidatableElementInterface
31
{
32
    use SchemaValidatableElementTrait;
33
34
35
    /**
36
     * SPSSODescriptor constructor.
37
     *
38
     * @param array<\SimpleSAML\SAML2\XML\md\AssertionConsumerService> $assertionConsumerService
39
     * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
40
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $authnRequestsSigned
41
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $wantAssertionsSigned
42
     * @param array<\SimpleSAML\SAML2\XML\md\AttributeConsumingService> $attributeConsumingService
43
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID
44
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil
45
     * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration
46
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
47
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL
48
     * @param array<\SimpleSAML\SAML2\XML\md\KeyDescriptor> $keyDescriptors
49
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
50
     * @param array<\SimpleSAML\SAML2\XML\md\ContactPerson> $contacts
51
     * @param array<\SimpleSAML\SAML2\XML\md\ArtifactResolutionService> $artifactResolutionService
52
     * @param array<\SimpleSAML\SAML2\XML\md\SingleLogoutService> $singleLogoutService
53
     * @param array<\SimpleSAML\SAML2\XML\md\ManageNameIDService> $manageNameIDService
54
     * @param array<\SimpleSAML\SAML2\XML\md\NameIDFormat> $nameIDFormat
55
     */
56
    public function __construct(
57
        protected array $assertionConsumerService,
58
        AnyURIListValue $protocolSupportEnumeration,
59
        protected ?BooleanValue $authnRequestsSigned = null,
60
        protected ?BooleanValue $wantAssertionsSigned = null,
61
        protected array $attributeConsumingService = [],
62
        ?IDValue $ID = null,
63
        ?SAMLDateTimeValue $validUntil = null,
64
        ?DurationValue $cacheDuration = null,
65
        ?Extensions $extensions = null,
66
        ?SAMLAnyURIValue $errorURL = null,
67
        array $keyDescriptors = [],
68
        ?Organization $organization = null,
69
        array $contacts = [],
70
        array $artifactResolutionService = [],
71
        array $singleLogoutService = [],
72
        array $manageNameIDService = [],
73
        array $nameIDFormat = [],
74
    ) {
75
        parent::__construct(
76
            $protocolSupportEnumeration,
77
            $ID,
78
            $validUntil,
79
            $cacheDuration,
80
            $extensions,
81
            $errorURL,
82
            $keyDescriptors,
83
            $organization,
84
            $contacts,
85
            $artifactResolutionService,
86
            $singleLogoutService,
87
            $manageNameIDService,
88
            $nameIDFormat,
89
        );
90
91
        Assert::maxCount($assertionConsumerService, C::UNBOUNDED_LIMIT);
92
        Assert::minCount($assertionConsumerService, 1, 'At least one AssertionConsumerService must be specified.');
93
        Assert::allIsInstanceOf(
94
            $assertionConsumerService,
95
            AssertionConsumerService::class,
96
            'All md:AssertionConsumerService endpoints must be an instance of AssertionConsumerService.',
97
        );
98
        Assert::maxCount($attributeConsumingService, C::UNBOUNDED_LIMIT);
99
        Assert::allIsInstanceOf(
100
            $attributeConsumingService,
101
            AttributeConsumingService::class,
102
            'All md:AttributeConsumingService endpoints must be an instance of AttributeConsumingService.',
103
        );
104
105
        /**
106
         * E87:  test that only one ACS is marked as default
107
         */
108
        Assert::maxCount(
109
            array_filter(
110
                $attributeConsumingService,
111
                function (AttributeConsumingService $acs) {
112
                    return $acs->getIsDefault()?->toBoolean() === true;
113
                },
114
            ),
115
            1,
116
            'At most one <AttributeConsumingService> element can have the attribute isDefault set to true.',
117
        );
118
    }
119
120
121
    /**
122
     * Collect the value of the AuthnRequestsSigned-property
123
     *
124
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
125
     */
126
    public function getAuthnRequestsSigned(): ?BooleanValue
127
    {
128
        return $this->authnRequestsSigned;
129
    }
130
131
132
    /**
133
     * Collect the value of the WantAssertionsSigned-property
134
     *
135
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
136
     */
137
    public function getWantAssertionsSigned(): ?BooleanValue
138
    {
139
        return $this->wantAssertionsSigned;
140
    }
141
142
143
    /**
144
     * Collect the value of the AssertionConsumerService-property
145
     *
146
     * @return \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
147
     */
148
    public function getAssertionConsumerService(): array
149
    {
150
        return $this->assertionConsumerService;
151
    }
152
153
154
    /**
155
     * Collect the value of the AttributeConsumingService-property
156
     *
157
     * @return \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
158
     */
159
    public function getAttributeConsumingService(): array
160
    {
161
        return $this->attributeConsumingService;
162
    }
163
164
165
    /**
166
     * Convert XML into a SPSSODescriptor
167
     *
168
     * @param \DOMElement $xml The XML element we should load
169
     * @return static
170
     *
171
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
172
     *   if the qualified name of the supplied element is wrong
173
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
174
     *   if the supplied element is missing one of the mandatory attributes
175
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
176
     *   if too many child-elements of a type are specified
177
     */
178
    public static function fromXML(DOMElement $xml): static
179
    {
180
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
181
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
182
183
        $orgs = Organization::getChildrenOfClass($xml);
184
        Assert::maxCount(
185
            $orgs,
186
            1,
187
            'More than one Organization found in this descriptor',
188
            TooManyElementsException::class,
189
        );
190
191
        $extensions = Extensions::getChildrenOfClass($xml);
192
        Assert::maxCount(
193
            $extensions,
194
            1,
195
            'Only one md:Extensions element is allowed.',
196
            TooManyElementsException::class,
197
        );
198
199
        $signature = Signature::getChildrenOfClass($xml);
200
        Assert::maxCount(
201
            $signature,
202
            1,
203
            'Only one ds:Signature element is allowed.',
204
            TooManyElementsException::class,
205
        );
206
207
        $spssod = new static(
208
            AssertionConsumerService::getChildrenOfClass($xml),
209
            self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
210
            self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null),
211
            self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null),
212
            AttributeConsumingService::getChildrenOfClass($xml),
213
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
214
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
215
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),
216
            !empty($extensions) ? $extensions[0] : null,
217
            self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null),
218
            KeyDescriptor::getChildrenOfClass($xml),
219
            !empty($orgs) ? $orgs[0] : null,
220
            ContactPerson::getChildrenOfClass($xml),
221
            ArtifactResolutionService::getChildrenOfClass($xml),
222
            SingleLogoutService::getChildrenOfClass($xml),
223
            ManageNameIDService::getChildrenOfClass($xml),
224
            NameIDFormat::getChildrenOfClass($xml),
225
        );
226
227
        if (!empty($signature)) {
228
            $spssod->setSignature($signature[0]);
229
            $spssod->setXML($xml);
230
        }
231
232
        return $spssod;
233
    }
234
235
236
    /**
237
     * Convert this assertion to an unsigned XML document.
238
     * This method does not sign the resulting XML document.
239
     *
240
     * @return \DOMElement The root element of the DOM tree
241
     */
242
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
243
    {
244
        $e = parent::toUnsignedXML($parent);
245
246
        if ($this->getAuthnRequestsSigned() !== null) {
247
            $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true));
248
        }
249
250
        if ($this->getWantAssertionsSigned() !== null) {
251
            $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true));
252
        }
253
254
        foreach ($this->getAssertionConsumerService() as $ep) {
255
            $ep->toXML($e);
256
        }
257
258
        foreach ($this->getAttributeConsumingService() as $acs) {
259
            $acs->toXML($e);
260
        }
261
262
        return $e;
263
    }
264
}
265