Passed
Pull Request — master (#280)
by Tim
02:41
created

AuthnAuthorityDescriptor::toUnsignedXML()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 8
nop 1
dl 0
loc 17
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\Assert\Assert;
9
use SimpleSAML\SAML2\Constants;
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 metadata AuthnAuthorityDescriptor.
19
 *
20
 * @package simplesamlphp/saml2
21
 */
22
final class AuthnAuthorityDescriptor extends AbstractRoleDescriptor
23
{
24
    /**
25
     * List of AuthnQueryService endpoints.
26
     *
27
     * @var \SimpleSAML\SAML2\XML\md\AbstractEndpointType[]
28
     */
29
    protected array $AuthnQueryServices = [];
30
31
    /**
32
     * List of AssertionIDRequestService endpoints.
33
     *
34
     * @var \SimpleSAML\SAML2\XML\md\AbstractEndpointType[]
35
     */
36
    protected array $AssertionIDRequestServices = [];
37
38
    /**
39
     * List of supported NameID formats.
40
     *
41
     * Array of strings.
42
     *
43
     * @var \SimpleSAML\SAML2\XML\md\NameIDFormat[]
44
     */
45
    protected array $NameIDFormats = [];
46
47
48
    /**
49
     * AuthnAuthorityDescriptor constructor.
50
     *
51
     * @param array $authnQueryServices
52
     * @param array $protocolSupportEnumeration
53
     * @param array $assertionIDRequestServices
54
     * @param array $nameIDFormats
55
     * @param string|null $ID
56
     * @param int|null $validUntil
57
     * @param string|null $cacheDuration
58
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
59
     * @param string|null $errorURL
60
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
61
     * @param array $keyDescriptors
62
     * @param array $contacts
63
     */
64
    public function __construct(
65
        array $authnQueryServices,
66
        array $protocolSupportEnumeration,
67
        array $assertionIDRequestServices = [],
68
        array $nameIDFormats = [],
69
        string $ID = null,
70
        ?int $validUntil = null,
71
        ?string $cacheDuration = null,
72
        ?Extensions $extensions = null,
73
        ?string $errorURL = null,
74
        ?Organization $organization = null,
75
        array $keyDescriptors = [],
76
        array $contacts = []
77
    ) {
78
        parent::__construct(
79
            $protocolSupportEnumeration,
80
            $ID,
81
            $validUntil,
82
            $cacheDuration,
83
            $extensions,
84
            $errorURL,
85
            $keyDescriptors,
86
            $organization,
87
            $contacts
88
        );
89
        $this->setAuthnQueryServices($authnQueryServices);
90
        $this->setAssertionIDRequestService($assertionIDRequestServices);
91
        $this->setNameIDFormat($nameIDFormats);
92
    }
93
94
95
    /**
96
     * Initialize an IDPSSODescriptor from an existing XML document.
97
     *
98
     * @param \DOMElement $xml The XML element we should load.
99
     * @return self
100
     *
101
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
102
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
103
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
104
     */
105
    public static function fromXML(DOMElement $xml): object
106
    {
107
        Assert::same($xml->localName, 'AuthnAuthorityDescriptor', InvalidDOMElementException::class);
108
        Assert::same($xml->namespaceURI, AuthnAuthorityDescriptor::NS, InvalidDOMElementException::class);
109
110
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
111
112
        $authnQueryServices = AuthnQueryService::getChildrenOfClass($xml);
113
        $assertionIDRequestServices = AssertionIDRequestService::getChildrenOfClass($xml);
114
        $nameIDFormats = NameIDFormat::getChildrenOfClass($xml);
115
116
        $validUntil = self::getAttribute($xml, 'validUntil', null);
117
118
        $orgs = Organization::getChildrenOfClass($xml);
119
        Assert::maxCount($orgs, 1, 'More than one Organization found in this descriptor', TooManyElementsException::class);
120
121
        $extensions = Extensions::getChildrenOfClass($xml);
122
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
123
124
        $signature = Signature::getChildrenOfClass($xml);
125
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
126
127
        $authority = new self(
128
            $authnQueryServices,
129
            preg_split('/[\s]+/', trim($protocols)),
130
            $assertionIDRequestServices,
131
            $nameIDFormats,
132
            self::getAttribute($xml, 'ID', null),
133
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
134
            self::getAttribute($xml, 'cacheDuration', null),
135
            !empty($extensions) ? $extensions[0] : null,
136
            self::getAttribute($xml, 'errorURL', null),
137
            !empty($orgs) ? $orgs[0] : null,
138
            KeyDescriptor::getChildrenOfClass($xml),
139
            ContactPerson::getChildrenOfClass($xml)
140
        );
141
142
        if (!empty($signature)) {
143
            $authority->setSignature($signature[0]);
144
        }
145
146
        $authority->setXML($xml);
147
148
        return $authority;
149
    }
150
151
152
    /**
153
     * Collect the AuthnQueryService endpoints
154
     *
155
     * @return \SimpleSAML\SAML2\XML\md\AbstractEndpointType[]
156
     */
157
    public function getAuthnQueryServices(): array
158
    {
159
        return $this->AuthnQueryServices;
160
    }
161
162
163
    /**
164
     * Set the AuthnQueryService endpoints
165
     *
166
     * @param \SimpleSAML\SAML2\XML\md\AbstractEndpointType[] $authnQueryServices
167
     * @throws \SimpleSAML\Assert\AssertionFailedException
168
     */
169
    protected function setAuthnQueryServices(array $authnQueryServices): void
170
    {
171
        Assert::minCount($authnQueryServices, 1, 'Missing at least one AuthnQueryService in AuthnAuthorityDescriptor.');
172
        Assert::allIsInstanceOf(
173
            $authnQueryServices,
174
            AbstractEndpointType::class,
175
            'AuthnQueryService must be an instance of EndpointType'
176
        );
177
        $this->AuthnQueryServices = $authnQueryServices;
178
    }
179
180
181
    /**
182
     * Collect the AssertionIDRequestService endpoints
183
     *
184
     * @return \SimpleSAML\SAML2\XML\md\AbstractEndpointType[]
185
     */
186
    public function getAssertionIDRequestServices(): array
187
    {
188
        return $this->AssertionIDRequestServices;
189
    }
190
191
192
    /**
193
     * Set the AssertionIDRequestService endpoints
194
     *
195
     * @param \SimpleSAML\SAML2\XML\md\AbstractEndpointType[] $assertionIDRequestServices
196
     * @throws \SimpleSAML\Assert\AssertionFailedException
197
     */
198
    protected function setAssertionIDRequestService(array $assertionIDRequestServices = []): void
199
    {
200
        Assert::allIsInstanceOf(
201
            $assertionIDRequestServices,
202
            AbstractEndpointType::class,
203
            'AssertionIDRequestServices must be an instance of EndpointType'
204
        );
205
        $this->AssertionIDRequestServices = $assertionIDRequestServices;
206
    }
207
208
209
    /**
210
     * Collect the values of the NameIDFormat
211
     *
212
     * @return \SimpleSAML\SAML2\XML\md\NameIDFormat[]
213
     */
214
    public function getNameIDFormats(): array
215
    {
216
        return $this->NameIDFormats;
217
    }
218
219
220
    /**
221
     * Set the values of the NameIDFormat
222
     *
223
     * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormats
224
     * @throws \SimpleSAML\Assert\AssertionFailedException
225
     */
226
    protected function setNameIDFormat(array $nameIDFormats): void
227
    {
228
        Assert::allIsInstanceOf($nameIDFormats, NameIDFormat::class);
229
        $this->NameIDFormats = $nameIDFormats;
230
    }
231
232
233
    /**
234
     * Convert this descriptor to an unsigned XML document.
235
     * This method does not sign the resulting XML document.
236
     *
237
     * @param \DOMElement|null $parent
238
     * @return \DOMElement The root element of the DOM tree
239
     */
240
    protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
241
    {
242
        $e = parent::toUnsignedXML($parent);
243
244
        foreach ($this->AuthnQueryServices as $ep) {
245
            $ep->toXML($e);
246
        }
247
248
        foreach ($this->AssertionIDRequestServices as $ep) {
249
            $ep->toXML($e);
250
        }
251
252
        foreach ($this->NameIDFormats as $nidFormat) {
253
            $nidFormat->toXML($e);
254
        }
255
256
        return $e;
257
    }
258
}
259