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

AuthnRequest::getConditions()   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 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\XML\saml\SubjectConfirmation;
13
use SAML2\Utils;
14
use Webmozart\Assert\Assert;
15
16
/**
17
 * Class for SAML 2 authentication request messages.
18
 *
19
 * @package SimpleSAMLphp
20
 */
21
class AuthnRequest extends AbstractRequest
22
{
23
    /**
24
     * @var \SAML2\XML\saml\Subject|null
25
     */
26
    protected $subject = null;
27
28
    /**
29
     * @var \SAML2\XML\samlp\Scoping|null
30
     */
31
    protected $scoping = null;
32
33
    /**
34
     * The options for what type of name identifier should be returned.
35
     *
36
     * @var \SAML2\XML\samlp\NameIDPolicy|null
37
     */
38
    protected $nameIdPolicy = null;
39
40
    /**
41
     * Whether the Identity Provider must authenticate the user again.
42
     *
43
     * @var bool|null
44
     */
45
    protected $forceAuthn = false;
46
47
    /**
48
     * Optional ProviderID attribute
49
     *
50
     * @var string|null
51
     */
52
    protected $ProviderName = null;
53
54
    /**
55
     * Set to true if this request is passive.
56
     *
57
     * @var bool|null
58
     */
59
    protected $isPassive = false;
60
61
    /**
62
     * The URL of the assertion consumer service where the response should be delivered.
63
     *
64
     * @var string|null
65
     */
66
    protected $assertionConsumerServiceURL;
67
68
    /**
69
     * What binding should be used when sending the response.
70
     *
71
     * @var string|null
72
     */
73
    protected $protocolBinding;
74
75
    /**
76
     * The index of the AttributeConsumingService.
77
     *
78
     * @var int|null
79
     */
80
    protected $attributeConsumingServiceIndex;
81
82
    /**
83
     * The index of the AssertionConsumerService.
84
     *
85
     * @var int|null
86
     */
87
    protected $assertionConsumerServiceIndex;
88
89
    /**
90
     * What authentication context was requested.
91
     *
92
     * @var \SAML2\XML\samlp\RequestedAuthnContext|null
93
     */
94
    protected $requestedAuthnContext;
95
96
    /**
97
     * @var \SAML2\XML\saml\Conditions|null
98
     */
99
    protected $conditions = null;
100
101
    /**
102
     * @var \SAML2\XML\saml\SubjectConfirmation[]
103
     */
104
    protected $subjectConfirmation = [];
105
106
107
    /**
108
     * Constructor for SAML 2 AuthnRequest
109
     *
110
     * @param \SAML2\XML\samlp\RequestedAuthnContext $requestedAuthnContext
111
     * @param \SAML2\XML\saml\Subject $subject
112
     * @param \SAML2\XML\samlp\NameIDPolicy $nameIdPolicy
113
     * @param \SAML2\XML\saml\Conditions $conditions
114
     * @param bool $forceAuthn
115
     * @param bool $isPassive
116
     * @param string $assertionConsumerServiceUrl
117
     * @param string $protocolBinding
118
     * @param int $attributeConsumingServiceIndex
119
     * @param string $providerName
120
     * @param \SAML2\XML\saml\Issuer|null $issuer
121
     * @param string|null $id
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
     * @throws \Exception
128
     */
129
    public function __construct(
130
        ?RequestedAuthnContext $requestedAuthnContext = null,
131
        ?Subject $subject = null,
132
        ?NameIDPolicy $nameIdPolicy = null,
133
        Conditions $conditions = null,
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
        ?Issuer $issuer = null,
141
        ?string $id = null,
142
        ?int $issueInstant = null,
143
        ?string $destination = null,
144
        ?string $consent = null,
145
        ?Extensions $extensions = null,
146
        ?Scoping $scoping = null
147
    ) {
148
        parent::__construct($issuer, $id, $issueInstant, $destination, $consent, $extensions);
149
150
        $this->setRequestedAuthnContext($requestedAuthnContext);
151
        $this->setSubject($subject);
152
        $this->setNameIdPolicy($nameIdPolicy);
153
        $this->setConditions($conditions);
154
155
        $this->setForceAuthn($forceAuthn);
156
        $this->setIsPassive($isPassive);
157
        $this->setAssertionConsumerServiceUrl($assertionConsumerServiceUrl);
158
        $this->setProtocolBinding($protocolBinding);
159
        $this->setAttributeConsumingServiceIndex($attributeConsumingServiceIndex);
160
        $this->setProviderName($providerName);
161
        $this->setScoping($scoping);
162
    }
163
164
165
    /**
166
     * @param \SAML2\XML\saml\Subject|null $subject
167
     * @return void
168
     */
169
    private function setSubject(?Subject $subject): void
170
    {
171
        $this->subject = $subject;
172
    }
173
174
175
    /**
176
     * @return \SAML2\XML\saml\Subject|null
177
     */
178
    public function getSubject(): ?Subject
179
    {
180
        return $this->subject;
181
    }
182
183
184
    /**
185
     * @param \SAML2\XML\samlp\Scoping|null $scoping
186
     * @return void
187
     */
188
    private function setScoping(?Scoping $scoping): void
189
    {
190
        $this->scoping = $scoping;
191
    }
192
193
194
    /**
195
     * @return \SAML2\XML\samlp\Scoping|null
196
     */
197
    public function getScoping(): ?Scoping
198
    {
199
        return $this->scoping;
200
    }
201
202
203
    /**
204
     * @param \SAML2\XML\saml\Conditions|null $conditions
205
     * @return void
206
     */
207
    private function setConditions(?Conditions $conditions): void
208
    {
209
        $this->conditions = $conditions;
210
    }
211
212
213
    /**
214
     * @return \SAML2\XML\saml\Conditions|null
215
     */
216
    public function getConditions(): ?Conditions
217
    {
218
        return $this->conditions;
219
    }
220
221
222
    /**
223
     * Retrieve the NameIdPolicy.
224
     *
225
     * @see \SAML2\AuthnRequest::setNameIdPolicy()
226
     * @return \SAML2\XML\samlp\NameIDPolicy|null The NameIdPolicy.
227
     */
228
    public function getNameIdPolicy(): ?NameIDPolicy
229
    {
230
        return $this->nameIdPolicy;
231
    }
232
233
234
    /**
235
     * Set the NameIDPolicy.
236
     *
237
     * @param \SAML2\XML\samlp\NameIDPolicy|null $nameIdPolicy The NameIDPolicy.
238
     * @return void
239
     */
240
    private function setNameIdPolicy(?NameIDPolicy $nameIdPolicy): void
241
    {
242
        $this->nameIdPolicy = $nameIdPolicy;
243
    }
244
245
246
    /**
247
     * Retrieve the value of the ForceAuthn attribute.
248
     *
249
     * @return bool|null The ForceAuthn attribute.
250
     */
251
    public function getForceAuthn(): ?bool
252
    {
253
        return $this->forceAuthn;
254
    }
255
256
257
    /**
258
     * Set the value of the ForceAuthn attribute.
259
     *
260
     * @param bool $forceAuthn The ForceAuthn attribute.
261
     * @return void
262
     */
263
    private function setForceAuthn(?bool $forceAuthn): void
264
    {
265
        $this->forceAuthn = $forceAuthn;
266
    }
267
268
269
    /**
270
     * Retrieve the value of the ProviderName attribute.
271
     *
272
     * @return string|null The ProviderName attribute.
273
     */
274
    public function getProviderName(): ?string
275
    {
276
        return $this->ProviderName;
277
    }
278
279
280
    /**
281
     * Set the value of the ProviderName attribute.
282
     *
283
     * @param string|null $ProviderName The ProviderName attribute.
284
     * @return void
285
     */
286
    private function setProviderName(?string $ProviderName): void
287
    {
288
        $this->ProviderName = $ProviderName;
289
    }
290
291
292
    /**
293
     * Retrieve the value of the IsPassive attribute.
294
     *
295
     * @return bool|null The IsPassive attribute.
296
     */
297
    public function getIsPassive(): ?bool
298
    {
299
        return $this->isPassive;
300
    }
301
302
303
    /**
304
     * Set the value of the IsPassive attribute.
305
     *
306
     * @param bool|null $isPassive The IsPassive attribute.
307
     * @return void
308
     */
309
    private function setIsPassive(?bool $isPassive): void
310
    {
311
        $this->isPassive = $isPassive;
312
    }
313
314
315
    /**
316
     * Retrieve the value of the AssertionConsumerServiceURL attribute.
317
     *
318
     * @return string|null The AssertionConsumerServiceURL attribute.
319
     */
320
    public function getAssertionConsumerServiceURL(): ?string
321
    {
322
        return $this->assertionConsumerServiceURL;
323
    }
324
325
326
    /**
327
     * Set the value of the AssertionConsumerServiceURL attribute.
328
     *
329
     * @param string|null $assertionConsumerServiceURL The AssertionConsumerServiceURL attribute.
330
     * @return void
331
     */
332
    private function setAssertionConsumerServiceURL(string $assertionConsumerServiceURL = null): void
333
    {
334
        $this->assertionConsumerServiceURL = $assertionConsumerServiceURL;
335
    }
336
337
338
    /**
339
     * Retrieve the value of the ProtocolBinding attribute.
340
     *
341
     * @return string|null The ProtocolBinding attribute.
342
     */
343
    public function getProtocolBinding(): ?string
344
    {
345
        return $this->protocolBinding;
346
    }
347
348
349
    /**
350
     * Set the value of the ProtocolBinding attribute.
351
     *
352
     * @param string $protocolBinding The ProtocolBinding attribute.
353
     * @return void
354
     */
355
    private function setProtocolBinding(string $protocolBinding = null): void
356
    {
357
        $this->protocolBinding = $protocolBinding;
358
    }
359
360
361
    /**
362
     * Retrieve the value of the AttributeConsumingServiceIndex attribute.
363
     *
364
     * @return int|null The AttributeConsumingServiceIndex attribute.
365
     */
366
    public function getAttributeConsumingServiceIndex(): ?int
367
    {
368
        return $this->attributeConsumingServiceIndex;
369
    }
370
371
372
    /**
373
     * Set the value of the AttributeConsumingServiceIndex attribute.
374
     *
375
     * @param int|null $attributeConsumingServiceIndex The AttributeConsumingServiceIndex attribute.
376
     * @return void
377
     */
378
    private function setAttributeConsumingServiceIndex(int $attributeConsumingServiceIndex = null): void
379
    {
380
        $this->attributeConsumingServiceIndex = $attributeConsumingServiceIndex;
381
    }
382
383
384
    /**
385
     * Retrieve the value of the AssertionConsumerServiceIndex attribute.
386
     *
387
     * @return int|null The AssertionConsumerServiceIndex attribute.
388
     */
389
    public function getAssertionConsumerServiceIndex(): ?int
390
    {
391
        return $this->assertionConsumerServiceIndex;
392
    }
393
394
395
    /**
396
     * Set the value of the AssertionConsumerServiceIndex attribute.
397
     *
398
     * @param int|null $assertionConsumerServiceIndex The AssertionConsumerServiceIndex attribute.
399
     * @return void
400
     */
401
    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...
402
    {
403
        $this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex;
404
    }
405
406
407
    /**
408
     * Retrieve the RequestedAuthnContext.
409
     *
410
     * @return \SAML2\XML\samlp\RequestedAuthnContext|null The RequestedAuthnContext.
411
     */
412
    public function getRequestedAuthnContext(): ?RequestedAuthnContext
413
    {
414
        return $this->requestedAuthnContext;
415
    }
416
417
418
    /**
419
     * Set the RequestedAuthnContext.
420
     *
421
     * @param \SAML2\XML\samlp\RequestedAuthnContext|null $requestedAuthnContext The RequestedAuthnContext.
422
     * @return void
423
     */
424
    private function setRequestedAuthnContext(RequestedAuthnContext $requestedAuthnContext = null): void
425
    {
426
        $this->requestedAuthnContext = $requestedAuthnContext;
427
    }
428
429
430
    /**
431
     * Retrieve the SubjectConfirmation elements we have in our Subject element.
432
     *
433
     * @return \SAML2\XML\saml\SubjectConfirmation[]
434
     */
435
    public function getSubjectConfirmation(): array
436
    {
437
        return $this->subjectConfirmation;
438
    }
439
440
441
    /**
442
     * Set the SubjectConfirmation elements that should be included in the assertion.
443
     *
444
     * @param array \SAML2\XML\saml\SubjectConfirmation[]
445
     * @return void
446
     */
447
    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...
448
    {
449
        Assert::allIsInstanceOf($subjectConfirmation, SubjectConfirmation::class);
450
        $this->subjectConfirmation = $subjectConfirmation;
451
    }
452
453
454
    /**
455
     * Convert XML into an AuthnRequest
456
     *
457
     * @param \DOMElement $xml The XML element we should load
458
     * @return \SAML2\XML\samlp\AuthnRequest
459
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
460
     * @throws \Exception
461
     */
462
    public static function fromXML(DOMElement $xml): object
463
    {
464
        Assert::same($xml->localName, 'AuthnRequest');
465
        Assert::same($xml->namespaceURI, AuthnRequest::NS);
466
        Assert::same('2.0', self::getAttribute($xml, 'Version'));
467
468
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
469
470
        $attributeConsumingServiceIndex = self::getAttribute($xml, 'AttributeConsumingServiceIndex', null);
471
        if ($attributeConsumingServiceIndex !== null) {
472
            $attributeConsumingServiceIndex = intval($attributeConsumingServiceIndex);
473
        }
474
475
        $conditions = Conditions::getChildrenOfClass($xml);
476
        Assert::maxCount($conditions, 1, 'Only one <saml:Conditions> element is allowed.');
477
478
        $nameIdPolicy = NameIDPolicy::getChildrenOfClass($xml);
479
        Assert::maxCount($nameIdPolicy, 1, 'Only one <samlp:NameIDPolicy> element is allowed.');
480
481
        $subject = Subject::getChildrenOfClass($xml);
482
        Assert::maxCount($subject, 1, 'Only one <saml:Subject> element is allowed.');
483
484
        $issuer = Issuer::getChildrenOfClass($xml);
485
        Assert::maxCount($issuer, 1, 'Only one <saml:Issuer> element is allowed.');
486
487
        $requestedAuthnContext = RequestedAuthnContext::getChildrenOfClass($xml);
488
        Assert::maxCount($requestedAuthnContext, 1, 'Only one <samlp:RequestedAuthnContext> element is allowed.');
489
490
        $extensions = Extensions::getChildrenOfClass($xml);
491
        Assert::maxCount($extensions, 1, 'Only one <samlp:Extensions> element is allowed.');
492
493
        $signature = Signature::getChildrenOfClass($xml);
494
        Assert::maxCount($signature, 1, 'Only one <ds:Signature> element is allowed.');
495
496
        $scoping = Scoping::getChildrenOfClass($xml);
497
        Assert::maxCount($scoping, 1, 'Only one <samlp:Scoping> element is allowed.');
498
499
500
        $request = new self(
501
            array_pop($requestedAuthnContext),
502
            array_pop($subject),
503
            array_pop($nameIdPolicy),
504
            array_pop($conditions),
505
            self::getBooleanAttribute($xml, 'ForceAuthn', null),
506
            self::getBooleanAttribute($xml, 'IsPassive', null),
507
            self::getAttribute($xml, 'AssertionConsumerServiceURL', null),
508
            self::getAttribute($xml, 'ProtocolBinding', null),
509
            $attributeConsumingServiceIndex,
510
            self::getAttribute($xml, 'ProviderName', null),
511
            array_pop($issuer),
512
            self::getAttribute($xml, 'ID'),
513
            $issueInstant,
514
            self::getAttribute($xml, 'Destination', null),
515
            self::getAttribute($xml, 'Consent', null),
516
            array_pop($extensions),
517
            array_pop($scoping)
518
        );
519
520
        if (!empty($signature)) {
521
            $request->setSignature($signature[0]);
522
            $request->messageContainedSignatureUponConstruction = true;
523
        }
524
525
        return $request;
526
    }
527
528
529
    /**
530
     * Convert this authentication request to an XML element.
531
     *
532
     * @return \DOMElement This authentication request.
533
     * @throws \Exception
534
     */
535
    public function toXML(?DOMElement $parent = null): DOMElement
536
    {
537
        $parent = parent::toXML($parent);
538
539
        if ($this->forceAuthn == true) {
540
            $parent->setAttribute('ForceAuthn', 'true');
541
        }
542
543
        if (!empty($this->ProviderName)) {
544
            $parent->setAttribute('ProviderName', $this->ProviderName);
545
        }
546
547
        if ($this->isPassive === true) {
548
            $parent->setAttribute('IsPassive', 'true');
549
        }
550
551
        if ($this->assertionConsumerServiceIndex !== null) {
552
            $parent->setAttribute('AssertionConsumerServiceIndex', strval($this->assertionConsumerServiceIndex));
553
        } else {
554
            if ($this->assertionConsumerServiceURL !== null) {
555
                $parent->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL);
556
            }
557
            if ($this->protocolBinding !== null) {
558
                $parent->setAttribute('ProtocolBinding', $this->protocolBinding);
559
            }
560
        }
561
562
        if ($this->attributeConsumingServiceIndex !== null) {
563
            $parent->setAttribute('AttributeConsumingServiceIndex', strval($this->attributeConsumingServiceIndex));
564
        }
565
566
        if ($this->subject !== null) {
567
            $this->subject->toXML($parent);
568
        }
569
570
        if ($this->nameIdPolicy !== null) {
571
            if (!$this->nameIdPolicy->isEmptyElement()) {
572
                $this->nameIdPolicy->toXML($parent);
573
            }
574
        }
575
576
        if ($this->conditions !== null) {
577
            if (!$this->conditions->isEmptyElement()) {
578
                $this->conditions->toXML($parent);
579
            }
580
        }
581
582
        if (!empty($this->requestedAuthnContext)) {
583
            $this->requestedAuthnContext->toXML($parent);
584
        }
585
586
        if ($this->scoping !== null) {
587
            if (!$this->scoping->isEmptyElement()) {
588
                $this->scoping->toXML($parent);
589
            }
590
        }
591
592
        return $this->signElement($parent);
593
    }
594
}
595