Passed
Pull Request — master (#226)
by Jaime Pérez
02:37
created

AuthnRequest::setNameIdPolicy()   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 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SAML2\XML\samlp;
6
7
use DOMElement;
8
use SAML2\XML\ds\Signature;
9
use SAML2\XML\saml\Conditions;
10
use SAML2\XML\saml\Issuer;
11
use SAML2\XML\saml\Subject;
12
use SAML2\Utils;
13
use Webmozart\Assert\Assert;
14
15
/**
16
 * Class for SAML 2 authentication request messages.
17
 *
18
 * @package SimpleSAMLphp
19
 */
20
class AuthnRequest extends AbstractRequest
21
{
22
    /**
23
     * @var \SAML2\XML\saml\Subject|null
24
     */
25
    protected $subject = null;
26
27
    /**
28
     * @var \SAML2\XML\samlp\Scoping|null
29
     */
30
    protected $scoping = null;
31
32
    /**
33
     * The options for what type of name identifier should be returned.
34
     *
35
     * @var \SAML2\XML\samlp\NameIDPolicy|null
36
     */
37
    protected $nameIdPolicy = null;
38
39
    /**
40
     * Whether the Identity Provider must authenticate the user again.
41
     *
42
     * @var bool|null
43
     */
44
    protected $forceAuthn = false;
45
46
    /**
47
     * Optional ProviderID attribute
48
     *
49
     * @var string|null
50
     */
51
    protected $ProviderName = null;
52
53
    /**
54
     * Set to true if this request is passive.
55
     *
56
     * @var bool|null
57
     */
58
    protected $isPassive = false;
59
60
    /**
61
     * The URL of the assertion consumer service where the response should be delivered.
62
     *
63
     * @var string|null
64
     */
65
    protected $assertionConsumerServiceURL;
66
67
    /**
68
     * What binding should be used when sending the response.
69
     *
70
     * @var string|null
71
     */
72
    protected $protocolBinding;
73
74
    /**
75
     * The index of the AttributeConsumingService.
76
     *
77
     * @var int|null
78
     */
79
    protected $attributeConsumingServiceIndex;
80
81
    /**
82
     * The index of the AssertionConsumerService.
83
     *
84
     * @var int|null
85
     */
86
    protected $assertionConsumerServiceIndex;
87
88
    /**
89
     * What authentication context was requested.
90
     *
91
     * @var \SAML2\XML\samlp\RequestedAuthnContext|null
92
     */
93
    protected $requestedAuthnContext;
94
95
    /**
96
     * @var \SAML2\XML\saml\Conditions|null
97
     */
98
    protected $conditions = null;
99
100
    /**
101
     * @var \SAML2\XML\saml\SubjectConfirmation[]
102
     */
103
    protected $subjectConfirmation = [];
104
105
106
    /**
107
     * Constructor for SAML 2 AuthnRequest
108
     *
109
     * @param \SAML2\XML\samlp\RequestedAuthnContext $requestedAuthnContext
110
     * @param \SAML2\XML\saml\Subject $subject
111
     * @param \SAML2\XML\samlp\NameIDPolicy $nameIdPolicy
112
     * @param \SAML2\XML\saml\Conditions $conditions
113
     * @param bool $forceAuthn
114
     * @param bool $isPassive
115
     * @param string $assertionConsumerServiceUrl
116
     * @param string $protocolBinding
117
     * @param int $attributeConsumingServiceIndex
118
     * @param string $providerName
119
     * @param \SAML2\XML\saml\Issuer|null $issuer
120
     * @param string|null $id
121
     * @param string|null $version
122
     * @param int|null $issueInstant
123
     * @param string|null $destination
124
     * @param string|null $consent
125
     * @param \SAML2\XML\samlp\Extensions|null $extensions
126
     * @param \SAML2\XML\samlp\Scoping|null $scoping
127
     */
128
    public function __construct(
129
        ?RequestedAuthnContext $requestedAuthnContext = null,
130
        ?Subject $subject = null,
131
        ?NameIDPolicy $nameIdPolicy = null,
132
        Conditions $conditions = null,
133
134
        ?bool $forceAuthn = null,
135
        ?bool $isPassive = null,
136
        ?string $assertionConsumerServiceUrl = null,
137
        ?string $protocolBinding = null,
138
        ?int $attributeConsumingServiceIndex = null,
139
        ?string $providerName = null,
140
141
        ?Issuer $issuer = null,
142
        ?string $id = null,
143
        ?string $version = null,
144
        ?int $issueInstant = null,
145
        ?string $destination = null,
146
        ?string $consent = null,
147
        ?Extensions $extensions = null,
148
        ?Scoping $scoping = null
149
    ) {
150
        parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions);
151
152
        $this->setRequestedAuthnContext($requestedAuthnContext);
153
        $this->setSubject($subject);
154
        $this->setNameIdPolicy($nameIdPolicy);
155
        $this->setConditions($conditions);
156
157
        $this->setForceAuthn($forceAuthn);
158
        $this->setIsPassive($isPassive);
159
        $this->setAssertionConsumerServiceUrl($assertionConsumerServiceUrl);
160
        $this->setProtocolBinding($protocolBinding);
161
        $this->setAttributeConsumingServiceIndex($attributeConsumingServiceIndex);
162
        $this->setProviderName($providerName);
163
        $this->setScoping($scoping);
164
    }
165
166
167
    /**
168
     * @param \SAML2\XML\saml\Subject|null $subject
169
     * @return void
170
     */
171
    private function setSubject(?Subject $subject): void
172
    {
173
        $this->subject = $subject;
174
    }
175
176
177
    /**
178
     * @return \SAML2\XML\saml\Subject|null
179
     */
180
    public function getSubject(): ?Subject
181
    {
182
        return $this->subject;
183
    }
184
185
186
    /**
187
     * @param \SAML2\XML\saml\Scoping|null $scoping
0 ignored issues
show
Bug introduced by
The type SAML2\XML\saml\Scoping 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...
188
     * @return void
189
     */
190
    private function setScoping(?Scoping $scoping): void
191
    {
192
        $this->scoping = $scoping;
193
    }
194
195
196
    /**
197
     * @return \SAML2\XML\saml\Scoping|null
198
     */
199
    public function getScoping(): ?Scoping
200
    {
201
        return $this->scoping;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->scoping also could return the type SAML2\XML\samlp\Scoping which is incompatible with the documented return type SAML2\XML\saml\Scoping|null.
Loading history...
202
    }
203
204
205
    /**
206
     * @param \SAML2\XML\saml\Conditions|null $conditions
207
     * @return void
208
     */
209
    private function setConditions(?Conditions $conditions): void
210
    {
211
        $this->conditions = $conditions;
212
    }
213
214
215
    /**
216
     * @return \SAML2\XML\saml\Conditions|null
217
     */
218
    public function getConditions(): ?Conditions
219
    {
220
        return $this->conditions;
221
    }
222
223
224
    /**
225
     * Retrieve the NameIdPolicy.
226
     *
227
     * @see \SAML2\AuthnRequest::setNameIdPolicy()
228
     * @return \SAML2\XML\samlp\NameIDPolicy|null The NameIdPolicy.
229
     */
230
    public function getNameIdPolicy(): ?NameIDPolicy
231
    {
232
        return $this->nameIdPolicy;
233
    }
234
235
236
    /**
237
     * Set the NameIDPolicy.
238
     *
239
     * @param \SAML2\XML\samlp\NameIDPolicy|null $nameIdPolicy The NameIDPolicy.
240
     * @return void
241
     */
242
    private function setNameIdPolicy(?NameIDPolicy $nameIdPolicy): void
243
    {
244
        $this->nameIdPolicy = $nameIdPolicy;
245
    }
246
247
248
    /**
249
     * Retrieve the value of the ForceAuthn attribute.
250
     *
251
     * @return bool|null The ForceAuthn attribute.
252
     */
253
    public function getForceAuthn(): ?bool
254
    {
255
        return $this->forceAuthn;
256
    }
257
258
259
    /**
260
     * Set the value of the ForceAuthn attribute.
261
     *
262
     * @param bool $forceAuthn The ForceAuthn attribute.
263
     * @return void
264
     */
265
    private function setForceAuthn(?bool $forceAuthn): void
266
    {
267
        $this->forceAuthn = $forceAuthn;
268
    }
269
270
271
    /**
272
     * Retrieve the value of the ProviderName attribute.
273
     *
274
     * @return string|null The ProviderName attribute.
275
     */
276
    public function getProviderName(): ?string
277
    {
278
        return $this->ProviderName;
279
    }
280
281
282
    /**
283
     * Set the value of the ProviderName attribute.
284
     *
285
     * @param string|null $ProviderName The ProviderName attribute.
286
     * @return void
287
     */
288
    private function setProviderName(?string $ProviderName): void
289
    {
290
        $this->ProviderName = $ProviderName;
291
    }
292
293
294
    /**
295
     * Retrieve the value of the IsPassive attribute.
296
     *
297
     * @return bool|null The IsPassive attribute.
298
     */
299
    public function getIsPassive(): ?bool
300
    {
301
        return $this->isPassive;
302
    }
303
304
305
    /**
306
     * Set the value of the IsPassive attribute.
307
     *
308
     * @param bool|null $isPassive The IsPassive attribute.
309
     * @return void
310
     */
311
    private function setIsPassive(?bool $isPassive): void
312
    {
313
        $this->isPassive = $isPassive;
314
    }
315
316
317
    /**
318
     * Retrieve the value of the AssertionConsumerServiceURL attribute.
319
     *
320
     * @return string|null The AssertionConsumerServiceURL attribute.
321
     */
322
    public function getAssertionConsumerServiceURL(): ?string
323
    {
324
        return $this->assertionConsumerServiceURL;
325
    }
326
327
328
    /**
329
     * Set the value of the AssertionConsumerServiceURL attribute.
330
     *
331
     * @param string|null $assertionConsumerServiceURL The AssertionConsumerServiceURL attribute.
332
     * @return void
333
     */
334
    private function setAssertionConsumerServiceURL(string $assertionConsumerServiceURL = null): void
335
    {
336
        $this->assertionConsumerServiceURL = $assertionConsumerServiceURL;
337
    }
338
339
340
    /**
341
     * Retrieve the value of the ProtocolBinding attribute.
342
     *
343
     * @return string|null The ProtocolBinding attribute.
344
     */
345
    public function getProtocolBinding(): ?string
346
    {
347
        return $this->protocolBinding;
348
    }
349
350
351
    /**
352
     * Set the value of the ProtocolBinding attribute.
353
     *
354
     * @param string $protocolBinding The ProtocolBinding attribute.
355
     * @return void
356
     */
357
    private function setProtocolBinding(string $protocolBinding = null): void
358
    {
359
        $this->protocolBinding = $protocolBinding;
360
    }
361
362
363
    /**
364
     * Retrieve the value of the AttributeConsumingServiceIndex attribute.
365
     *
366
     * @return int|null The AttributeConsumingServiceIndex attribute.
367
     */
368
    public function getAttributeConsumingServiceIndex(): ?int
369
    {
370
        return $this->attributeConsumingServiceIndex;
371
    }
372
373
374
    /**
375
     * Set the value of the AttributeConsumingServiceIndex attribute.
376
     *
377
     * @param int|null $attributeConsumingServiceIndex The AttributeConsumingServiceIndex attribute.
378
     * @return void
379
     */
380
    private function setAttributeConsumingServiceIndex(int $attributeConsumingServiceIndex = null): void
381
    {
382
        $this->attributeConsumingServiceIndex = $attributeConsumingServiceIndex;
383
    }
384
385
386
    /**
387
     * Retrieve the value of the AssertionConsumerServiceIndex attribute.
388
     *
389
     * @return int|null The AssertionConsumerServiceIndex attribute.
390
     */
391
    public function getAssertionConsumerServiceIndex(): ?int
392
    {
393
        return $this->assertionConsumerServiceIndex;
394
    }
395
396
397
    /**
398
     * Set the value of the AssertionConsumerServiceIndex attribute.
399
     *
400
     * @param int|null $assertionConsumerServiceIndex The AssertionConsumerServiceIndex attribute.
401
     * @return void
402
     */
403
    private function setAssertionConsumerServiceIndex(int $assertionConsumerServiceIndex = null): void
0 ignored issues
show
Unused Code introduced by
The method setAssertionConsumerServiceIndex() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
404
    {
405
        $this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex;
406
    }
407
408
409
    /**
410
     * Retrieve the RequestedAuthnContext.
411
     *
412
     * @return \SAML2\XML\samlp\RequestedAuthnContext|null The RequestedAuthnContext.
413
     */
414
    public function getRequestedAuthnContext(): ?RequestedAuthnContext
415
    {
416
        return $this->requestedAuthnContext;
417
    }
418
419
420
    /**
421
     * Set the RequestedAuthnContext.
422
     *
423
     * @param \SAML2\XML\samlp\RequestedAuthnContext|null $requestedAuthnContext The RequestedAuthnContext.
424
     * @return void
425
     */
426
    private function setRequestedAuthnContext(RequestedAuthnContext $requestedAuthnContext = null): void
427
    {
428
        $this->requestedAuthnContext = $requestedAuthnContext;
429
    }
430
431
432
    /**
433
     * Retrieve the SubjectConfirmation elements we have in our Subject element.
434
     *
435
     * @return \SAML2\XML\saml\SubjectConfirmation[]
436
     */
437
    public function getSubjectConfirmation(): array
438
    {
439
        return $this->subjectConfirmation;
440
    }
441
442
443
    /**
444
     * Set the SubjectConfirmation elements that should be included in the assertion.
445
     *
446
     * @param array \SAML2\XML\saml\SubjectConfirmation[]
447
     * @return void
448
     */
449
    private function setSubjectConfirmation(array $subjectConfirmation): void
0 ignored issues
show
Unused Code introduced by
The method setSubjectConfirmation() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
450
    {
451
        $this->subjectConfirmation = $subjectConfirmation;
452
    }
453
454
455
    /**
456
     * Convert XML into an AuthnRequest
457
     *
458
     * @param \DOMElement $xml The XML element we should load
459
     * @return \SAML2\XML\samlp\AuthnRequest
460
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
461
     */
462
    public static function fromXML(DOMElement $xml): object
463
    {
464
        Assert::same($xml->localName, 'AuthnRequest');
465
        Assert::same($xml->namespaceURI, AuthnRequest::NS);
466
467
        $id = self::getAttribute($xml, 'ID');
468
        $version = self::getAttribute($xml, 'Version');
469
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
470
        $inResponseTo = self::getAttribute($xml, 'InResponseTo', null);
0 ignored issues
show
Unused Code introduced by
The assignment to $inResponseTo is dead and can be removed.
Loading history...
471
        $destination = self::getAttribute($xml, 'Destination', null);
472
        $consent = self::getAttribute($xml, 'Consent', null);
473
474
        $forceAuthn = self::getBooleanAttribute($xml, 'ForceAuthn', 'false');
475
        $isPassive = self::getBooleanAttribute($xml, 'IsPassive', 'false');
476
477
        $assertionConsumerServiceUrl = self::getAttribute($xml, 'AssertionConsumerServiceURL', null);
478
        $protocolBinding = self::getAttribute($xml, 'ProtocolBinding', null);
479
480
        $attributeConsumingServiceIndex = self::getAttribute($xml, 'AttributeConsumingServiceIndex', null);
481
        if ($attributeConsumingServiceIndex !== null) {
482
            $attributeConsumingServiceIndex = intval($attributeConsumingServiceIndex);
483
        }
484
        $providerName = self::getAttribute($xml, 'ProviderName', null);
485
486
        $conditions = Conditions::getChildrenOfClass($xml);
487
        Assert::maxCount($conditions, 1, 'Only one <saml:Conditions> element is allowed.');
488
489
        $nameIdPolicy = NameIDPolicy::getChildrenOfClass($xml);
490
        Assert::maxCount($nameIdPolicy, 1, 'Only one <samlp:NameIDPolicy> element is allowed.');
491
492
        $subject = Subject::getChildrenOfClass($xml);
493
        Assert::maxCount($subject, 1, 'Only one <saml:Subject> element is allowed.');
494
495
        $issuer = Issuer::getChildrenOfClass($xml);
496
        Assert::maxCount($issuer, 1, 'Only one <saml:Issuer> element is allowed.');
497
498
        $requestedAuthnContext = RequestedAuthnContext::getChildrenOfClass($xml);
499
        Assert::maxCount($requestedAuthnContext, 1, 'Only one <samlp:RequestedAuthnContext> element is allowed.');
500
501
        $extensions = Extensions::getChildrenOfClass($xml);
502
        Assert::maxCount($extensions, 1, 'Only one <samlp:Extensions> element is allowed.');
503
504
        $signature = Signature::getChildrenOfClass($xml);
505
        Assert::maxCount($signature, 1, 'Only one <ds:Signature> element is allowed.');
506
507
        $scoping = Scoping::getChildrenOfClass($xml);
508
        Assert::maxCount($scoping, 1, 'Only one <samlp:Scoping> element is allowed.');
509
510
511
        $request = new self(
512
            array_pop($requestedAuthnContext),
513
            array_pop($subject),
514
            array_pop($nameIdPolicy),
515
            array_pop($conditions),
516
517
            $forceAuthn,
518
            $isPassive,
519
            $assertionConsumerServiceUrl,
520
            $protocolBinding,
521
            $attributeConsumingServiceIndex,
522
            $providerName,
523
524
            array_pop($issuer),
525
            $id,
526
            $version,
527
            $issueInstant,
528
            $destination,
529
            $consent,
530
            array_pop($extensions),
531
            array_pop($scoping)
532
        );
533
534
        if (!empty($signature)) {
535
            $request->setSignature($signature[0]);
536
            $request->messageContainedSignatureUponConstruction = true;
537
        }
538
539
        return $request;
540
    }
541
542
543
    /**
544
     * Convert this authentication request to an XML element.
545
     *
546
     * @return \DOMElement This authentication request.
547
     */
548
    public function toXML(?DOMElement $parent = null): DOMElement
549
    {
550
        Assert::null($parent);
551
552
        $parent = parent::toXML($parent);
553
554
        if ($this->forceAuthn) {
555
            $parent->setAttribute('ForceAuthn', 'true');
556
        }
557
558
        if (!empty($this->ProviderName)) {
559
            $parent->setAttribute('ProviderName', $this->ProviderName);
560
        }
561
562
        if ($this->isPassive) {
563
            $parent->setAttribute('IsPassive', 'true');
564
        }
565
566
        if ($this->assertionConsumerServiceIndex !== null) {
567
            $parent->setAttribute('AssertionConsumerServiceIndex', strval($this->assertionConsumerServiceIndex));
568
        } else {
569
            if ($this->assertionConsumerServiceURL !== null) {
570
                $parent->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL);
571
            }
572
            if ($this->protocolBinding !== null) {
573
                $parent->setAttribute('ProtocolBinding', $this->protocolBinding);
574
            }
575
        }
576
577
        if ($this->attributeConsumingServiceIndex !== null) {
578
            $parent->setAttribute('AttributeConsumingServiceIndex', strval($this->attributeConsumingServiceIndex));
579
        }
580
581
        if ($this->subject !== null) {
582
            $this->subject->toXML($parent);
583
        }
584
585
        if ($this->nameIdPolicy !== null) {
586
            if (!$this->nameIdPolicy->isEmptyElement()) {
587
                $this->nameIdPolicy->toXML($parent);
588
            }
589
        }
590
591
        if ($this->conditions !== null) {
592
            if (!$this->conditions->isEmptyElement()) {
593
                $this->conditions->toXML($parent);
594
            }
595
        }
596
597
        if (!empty($this->requestedAuthnContext)) {
598
            $this->requestedAuthnContext->toXML($parent);
599
        }
600
601
        if ($this->scoping !== null) {
602
            if (!$this->scoping->isEmptyElement()) {
603
                $this->scoping->toXML($parent);
604
            }
605
        }
606
607
        return $this->signElement($parent);
608
    }
609
}
610