AuthnRequest::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 18
dl 0
loc 36
rs 9.8333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\samlp;
6
7
use DOMElement;
8
use SimpleSAML\SAML2\Assert\Assert;
9
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Excepti...VersionTooHighException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Excepti...tVersionTooLowException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
12
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
13
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Type\SAMLDateTimeValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use SimpleSAML\SAML2\Type\SAMLStringValue;
15
use SimpleSAML\SAML2\XML\saml\Conditions;
16
use SimpleSAML\SAML2\XML\saml\Issuer;
17
use SimpleSAML\SAML2\XML\saml\Subject;
18
use SimpleSAML\XML\SchemaValidatableElementInterface;
19
use SimpleSAML\XML\SchemaValidatableElementTrait;
20
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
21
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
22
use SimpleSAML\XMLSchema\Type\BooleanValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSchema\Type\BooleanValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use SimpleSAML\XMLSchema\Type\IDValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSchema\Type\IDValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use SimpleSAML\XMLSchema\Type\UnsignedShortValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSchema\Type\UnsignedShortValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use SimpleSAML\XMLSecurity\XML\ds\Signature;
26
27
use function array_pop;
28
use function strval;
29
30
/**
31
 * Class for SAML 2 authentication request messages.
32
 *
33
 * @package simplesamlphp/saml2
34
 */
35
class AuthnRequest extends AbstractRequest implements SchemaValidatableElementInterface
36
{
37
    use SchemaValidatableElementTrait;
38
39
40
    /**
41
     * Constructor for SAML 2 AuthnRequest
42
     *
43
     * @param \SimpleSAML\XMLSchema\Type\IDValue $id
44
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant
45
     * @param \SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext|null $requestedAuthnContext
46
     * @param \SimpleSAML\SAML2\XML\saml\Subject|null $subject
47
     * @param \SimpleSAML\SAML2\XML\samlp\NameIDPolicy|null $nameIdPolicy
48
     * @param \SimpleSAML\SAML2\XML\saml\Conditions|null $conditions
49
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $forceAuthn
50
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $isPassive
51
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $assertionConsumerServiceURL
52
     * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null $assertionConsumerServiceIndex
53
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $protocolBinding
54
     * @param \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null $attributeConsumingServiceIndex
55
     * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $providerName
56
     * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
57
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination
58
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent
59
     * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions
60
     * @param \SimpleSAML\SAML2\XML\samlp\Scoping|null $scoping
61
     *
62
     * @throws \Exception
63
     */
64
    final public function __construct(
65
        IDValue $id,
66
        SAMLDateTimeValue $issueInstant,
67
        protected ?RequestedAuthnContext $requestedAuthnContext = null,
68
        protected ?Subject $subject = null,
69
        protected ?NameIDPolicy $nameIdPolicy = null,
70
        protected ?Conditions $conditions = null,
71
        protected ?BooleanValue $forceAuthn = null,
72
        protected ?BooleanValue $isPassive = null,
73
        protected ?SAMLAnyURIValue $assertionConsumerServiceURL = null,
74
        protected ?UnsignedShortValue $assertionConsumerServiceIndex = null,
75
        protected ?SAMLAnyURIValue $protocolBinding = null,
76
        protected ?UnsignedShortValue $attributeConsumingServiceIndex = null,
77
        protected ?SAMLStringValue $providerName = null,
78
        ?Issuer $issuer = null,
79
        ?SAMLAnyURIValue $destination = null,
80
        ?SAMLAnyURIValue $consent = null,
81
        ?Extensions $extensions = null,
82
        protected ?Scoping $scoping = null,
83
    ) {
84
        Assert::oneOf(
85
            null,
86
            [$assertionConsumerServiceURL, $assertionConsumerServiceIndex],
87
            'The AssertionConsumerServiceURL and AssertionConsumerServiceIndex are mutually exclusive;'
88
            . ' please specify one or the other.',
89
            ProtocolViolationException::class,
90
        );
91
        Assert::oneOf(
92
            null,
93
            [$protocolBinding, $assertionConsumerServiceIndex],
94
            'The ProtocolBinding and AssertionConsumerServiceIndex are mutually exclusive;'
95
            . ' please specify one or the other.',
96
            ProtocolViolationException::class,
97
        );
98
99
        parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions);
100
    }
101
102
103
    /**
104
     * @return \SimpleSAML\SAML2\XML\saml\Subject|null
105
     */
106
    public function getSubject(): ?Subject
107
    {
108
        return $this->subject;
109
    }
110
111
112
    /**
113
     * @return \SimpleSAML\SAML2\XML\samlp\Scoping|null
114
     */
115
    public function getScoping(): ?Scoping
116
    {
117
        return $this->scoping;
118
    }
119
120
121
    /**
122
     * @return \SimpleSAML\SAML2\XML\saml\Conditions|null
123
     */
124
    public function getConditions(): ?Conditions
125
    {
126
        return $this->conditions;
127
    }
128
129
130
    /**
131
     * Retrieve the NameIdPolicy.
132
     *
133
     * @return \SimpleSAML\SAML2\XML\samlp\NameIDPolicy|null The NameIdPolicy.
134
     */
135
    public function getNameIdPolicy(): ?NameIDPolicy
136
    {
137
        return $this->nameIdPolicy;
138
    }
139
140
141
    /**
142
     * Retrieve the value of the ForceAuthn attribute.
143
     *
144
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null The ForceAuthn attribute.
145
     */
146
    public function getForceAuthn(): ?BooleanValue
147
    {
148
        return $this->forceAuthn;
149
    }
150
151
152
    /**
153
     * Retrieve the value of the ProviderName attribute.
154
     *
155
     * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null The ProviderName attribute.
156
     */
157
    public function getProviderName(): ?SAMLStringValue
158
    {
159
        return $this->providerName;
160
    }
161
162
163
    /**
164
     * Retrieve the value of the IsPassive attribute.
165
     *
166
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null The IsPassive attribute.
167
     */
168
    public function getIsPassive(): ?BooleanValue
169
    {
170
        return $this->isPassive;
171
    }
172
173
174
    /**
175
     * Retrieve the value of the AssertionConsumerServiceURL attribute.
176
     *
177
     * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The AssertionConsumerServiceURL attribute.
178
     */
179
    public function getAssertionConsumerServiceURL(): ?SAMLAnyURIValue
180
    {
181
        return $this->assertionConsumerServiceURL;
182
    }
183
184
185
    /**
186
     * Retrieve the value of the ProtocolBinding attribute.
187
     *
188
     * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The ProtocolBinding attribute.
189
     */
190
    public function getProtocolBinding(): ?SAMLAnyURIValue
191
    {
192
        return $this->protocolBinding;
193
    }
194
195
196
    /**
197
     * Retrieve the value of the AttributeConsumingServiceIndex attribute.
198
     *
199
     * @return \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null The AttributeConsumingServiceIndex attribute.
200
     */
201
    public function getAttributeConsumingServiceIndex(): ?UnsignedShortValue
202
    {
203
        return $this->attributeConsumingServiceIndex;
204
    }
205
206
207
    /**
208
     * Retrieve the value of the AssertionConsumerServiceIndex attribute.
209
     *
210
     * @return \SimpleSAML\XMLSchema\Type\UnsignedShortValue|null The AssertionConsumerServiceIndex attribute.
211
     */
212
    public function getAssertionConsumerServiceIndex(): ?UnsignedShortValue
213
    {
214
        return $this->assertionConsumerServiceIndex;
215
    }
216
217
218
    /**
219
     * Retrieve the RequestedAuthnContext.
220
     *
221
     * @return \SimpleSAML\SAML2\XML\samlp\RequestedAuthnContext|null The RequestedAuthnContext.
222
     */
223
    public function getRequestedAuthnContext(): ?RequestedAuthnContext
224
    {
225
        return $this->requestedAuthnContext;
226
    }
227
228
229
    /**
230
     * Convert XML into an AuthnRequest
231
     *
232
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
233
     *   if the qualified name of the supplied element is wrong
234
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
235
     *   if the supplied element is missing one of the mandatory attributes
236
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
237
     *   if too many child-elements of a type are specified
238
     */
239
    public static function fromXML(DOMElement $xml): static
240
    {
241
        Assert::same($xml->localName, 'AuthnRequest', InvalidDOMElementException::class);
242
        Assert::same($xml->namespaceURI, AuthnRequest::NS, InvalidDOMElementException::class);
243
244
        $version = self::getAttribute($xml, 'Version', SAMLStringValue::class);
245
        Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class);
246
        Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class);
247
248
        $conditions = Conditions::getChildrenOfClass($xml);
249
        Assert::maxCount(
250
            $conditions,
251
            1,
252
            'Only one <saml:Conditions> element is allowed.',
253
            TooManyElementsException::class,
254
        );
255
256
        $nameIdPolicy = NameIDPolicy::getChildrenOfClass($xml);
257
        Assert::maxCount(
258
            $nameIdPolicy,
259
            1,
260
            'Only one <samlp:NameIDPolicy> element is allowed.',
261
            TooManyElementsException::class,
262
        );
263
264
        $subject = Subject::getChildrenOfClass($xml);
265
        Assert::maxCount($subject, 1, 'Only one <saml:Subject> element is allowed.', TooManyElementsException::class);
266
267
        $issuer = Issuer::getChildrenOfClass($xml);
268
        Assert::maxCount($issuer, 1, 'Only one <saml:Issuer> element is allowed.', TooManyElementsException::class);
269
270
        $requestedAuthnContext = RequestedAuthnContext::getChildrenOfClass($xml);
271
        Assert::maxCount(
272
            $requestedAuthnContext,
273
            1,
274
            'Only one <samlp:RequestedAuthnContext> element is allowed.',
275
            TooManyElementsException::class,
276
        );
277
278
        $extensions = Extensions::getChildrenOfClass($xml);
279
        Assert::maxCount(
280
            $extensions,
281
            1,
282
            'Only one <samlp:Extensions> element is allowed.',
283
            TooManyElementsException::class,
284
        );
285
286
        $signature = Signature::getChildrenOfClass($xml);
287
        Assert::maxCount(
288
            $signature,
289
            1,
290
            'Only one <ds:Signature> element is allowed.',
291
            TooManyElementsException::class,
292
        );
293
294
        $scoping = Scoping::getChildrenOfClass($xml);
295
        Assert::maxCount($scoping, 1, 'Only one <samlp:Scoping> element is allowed.', TooManyElementsException::class);
296
297
        $request = new static(
298
            self::getAttribute($xml, 'ID', IDValue::class),
299
            self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class),
300
            array_pop($requestedAuthnContext),
301
            array_pop($subject),
302
            array_pop($nameIdPolicy),
303
            array_pop($conditions),
304
            self::getOptionalAttribute($xml, 'ForceAuthn', BooleanValue::class, null),
305
            self::getOptionalAttribute($xml, 'IsPassive', BooleanValue::class, null),
306
            self::getOptionalAttribute($xml, 'AssertionConsumerServiceURL', SAMLAnyURIValue::class, null),
307
            self::getOptionalAttribute($xml, 'AssertionConsumerServiceIndex', UnsignedShortValue::class, null),
308
            self::getOptionalAttribute($xml, 'ProtocolBinding', SAMLAnyURIValue::class, null),
309
            self::getOptionalAttribute($xml, 'AttributeConsumingServiceIndex', UnsignedShortValue::class, null),
310
            self::getOptionalAttribute($xml, 'ProviderName', SAMLStringValue::class, null),
311
            array_pop($issuer),
312
            self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null),
313
            self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null),
314
            array_pop($extensions),
315
            array_pop($scoping),
316
        );
317
318
        if (!empty($signature)) {
319
            $request->setSignature($signature[0]);
320
            $request->messageContainedSignatureUponConstruction = true;
321
            $request->setXML($xml);
322
        }
323
324
        return $request;
325
    }
326
327
328
    /**
329
     * Convert this message to an unsigned XML document.
330
     * This method does not sign the resulting XML document.
331
     */
332
    protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
333
    {
334
        $e = parent::toUnsignedXML($parent);
335
336
        if ($this->getForceAuthn() === true) {
0 ignored issues
show
introduced by
The condition $this->getForceAuthn() === true is always false.
Loading history...
337
            $e->setAttribute('ForceAuthn', strval($this->getForceAuthn()));
338
        }
339
340
        if ($this->getProviderName() !== null) {
341
            $e->setAttribute('ProviderName', strval($this->getProviderName()));
342
        }
343
344
        if ($this->getIsPassive() === true) {
0 ignored issues
show
introduced by
The condition $this->getIsPassive() === true is always false.
Loading history...
345
            $e->setAttribute('IsPassive', strval($this->getIsPassive()));
346
        }
347
348
        if ($this->getAssertionConsumerServiceIndex() !== null) {
349
            $e->setAttribute('AssertionConsumerServiceIndex', strval($this->getAssertionConsumerServiceIndex()));
350
        } else {
351
            if ($this->getAssertionConsumerServiceURL() !== null) {
352
                $e->setAttribute('AssertionConsumerServiceURL', strval($this->getAssertionConsumerServiceURL()));
353
            }
354
            if ($this->getProtocolBinding() !== null) {
355
                $e->setAttribute('ProtocolBinding', strval($this->getProtocolBinding()));
356
            }
357
        }
358
359
        if ($this->getAttributeConsumingServiceIndex() !== null) {
360
            $e->setAttribute('AttributeConsumingServiceIndex', strval($this->getAttributeConsumingServiceIndex()));
361
        }
362
363
        $this->getSubject()?->toXML($e);
364
365
        $nameIdPolicy = $this->getNameIdPolicy();
366
        if ($nameIdPolicy !== null && !$nameIdPolicy->isEmptyElement()) {
367
            $nameIdPolicy->toXML($e);
368
        }
369
370
        $conditions = $this->getConditions();
371
        if ($conditions !== null && !$conditions->isEmptyElement()) {
372
            $conditions->toXML($e);
373
        }
374
375
        $this->getRequestedAuthnContext()?->toXML($e);
376
377
        $scoping = $this->getScoping();
378
        if ($scoping !== null && !$scoping->isEmptyElement()) {
379
            $scoping->toXML($e);
380
        }
381
382
        return $e;
383
    }
384
}
385