Passed
Push — master ( c23650...91ab10 )
by Tim
02:35
created

AssertionIDRequest::toUnsignedXML()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\samlp;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
10
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
11
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
12
use SimpleSAML\SAML2\XML\saml\AssertionIDRef;
13
use SimpleSAML\SAML2\XML\saml\Issuer;
14
use SimpleSAML\XML\Exception\InvalidDOMElementException;
15
use SimpleSAML\XML\Exception\TooManyElementsException;
16
use SimpleSAML\XML\Utils as XMLUtils;
17
use SimpleSAML\XMLSecurity\XML\ds\Signature;
18
19
use function array_pop;
20
use function preg_replace;
21
use function version_compare;
22
23
/**
24
 * @package simplesamlphp/saml2
25
 */
26
final class AssertionIDRequest extends AbstractRequest
27
{
28
    /**
29
     * Initialize an AssertionIDRequest.
30
     *
31
     * @param \SimpleSAML\SAML2\XML\saml\AssertionIDRef[] $assertionIDRef
32
     * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
33
     * @param string|null $id
34
     * @param string $version
35
     * @param int|null $issueInstant
36
     * @param string|null $destination
37
     * @param string|null $consent
38
     * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions
39
     *
40
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
41
     */
42
    public function __construct(
43
        protected array $assertionIDRef,
44
        ?Issuer $issuer = null,
45
        ?string $id = null,
46
        string $version = '2.0',
47
        ?int $issueInstant = null,
48
        ?string $destination = null,
49
        ?string $consent = null,
50
        ?Extensions $extensions = null,
51
    ) {
52
        Assert::allIsInstanceOf($assertionIDRef, AssertionIDRef::class, InvalidDOMElementException::class);
53
54
        parent::__construct(
55
            $issuer,
56
            $id,
57
            $version,
58
            $issueInstant,
59
            $destination,
60
            $consent,
61
            $extensions,
62
        );
63
    }
64
65
66
67
    /**
68
     * @return \SimpleSAML\SAML2\XML\saml\AssertionIDRef[]
69
     */
70
    public function getAssertionIDRef(): array
71
    {
72
        return $this->assertionIDRef;
73
    }
74
75
76
    /**
77
     * Convert XML into a AssertionIDRequest element
78
     *
79
     * @param \DOMElement $xml The XML element we should load
80
     * @return static
81
     *
82
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
83
     *   If the qualified name of the supplied element is wrong
84
     */
85
    public static function fromXML(DOMElement $xml): static
86
    {
87
        Assert::same($xml->localName, 'AssertionIDRequest', InvalidDOMElementException::class);
88
        Assert::same($xml->namespaceURI, AssertionIDRequest::NS, InvalidDOMElementException::class);
89
90
        $assertionIDRef = AssertionIDRef::getChildrenOfClass($xml);
91
        Assert::minCount(
92
            $assertionIDRef,
93
            1,
94
            'At least one <samlp:AssertionIDRef> element is required.',
95
            TooManyElementsException::class,
96
        );
97
98
        $issuer = Issuer::getChildrenOfClass($xml);
99
        Assert::maxCount($issuer, 1, 'Only one <saml:Issuer> element is allowed.', TooManyElementsException::class);
100
101
        /** @psalm-var string $version */
102
        $version = self::getAttribute($xml, 'Version');
103
        Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class);
0 ignored issues
show
Bug introduced by
It seems like $version can also be of type null; however, parameter $version2 of version_compare() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

103
        Assert::true(version_compare('2.0', /** @scrutinizer ignore-type */ $version, '<='), RequestVersionTooLowException::class);
Loading history...
104
        Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class);
105
106
        /** @psalm-var string $issueInstant */
107
        $issueInstant = self::getAttribute($xml, 'IssueInstant');
108
        // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
109
        $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
110
111
        Assert::validDateTimeZulu($issueInstant, ProtocolViolationException::class);
112
        $issueInstant = XMLUtils::xsDateTimeToTimestamp($issueInstant);
113
114
        $extensions = Extensions::getChildrenOfClass($xml);
115
        Assert::maxCount(
116
            $extensions,
117
            1,
118
            'Only one <samlp:Extensions> element is allowed.',
119
            TooManyElementsException::class,
120
        );
121
122
        $signature = Signature::getChildrenOfClass($xml);
123
        Assert::maxCount(
124
            $signature,
125
            1,
126
            'Only one <ds:Signature> element is allowed.',
127
            TooManyElementsException::class,
128
        );
129
130
        $request = new static(
131
            $assertionIDRef,
132
            array_pop($issuer),
133
            self::getAttribute($xml, 'ID'),
134
            $version,
0 ignored issues
show
Bug introduced by
It seems like $version can also be of type null; however, parameter $version of SimpleSAML\SAML2\XML\sam...DRequest::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

134
            /** @scrutinizer ignore-type */ $version,
Loading history...
135
            $issueInstant,
136
            self::getAttribute($xml, 'Destination', null),
137
            self::getAttribute($xml, 'Consent', null),
138
            array_pop($extensions),
139
        );
140
141
        if (!empty($signature)) {
142
            $request->setSignature($signature[0]);
143
            $request->messageContainedSignatureUponConstruction = true;
144
            $request->setXML($xml);
145
        }
146
147
        return $request;
148
    }
149
150
151
    /**
152
     * Convert this AssertionIDRequest element to XML.
153
     *
154
     * @param \DOMElement|null $parent The element we should append this AssertionIDRequest element to.
155
     * @return \DOMElement
156
     */
157
    public function toUnsignedXML(DOMElement $parent = null): DOMElement
158
    {
159
        $e = parent::toUnsignedXML($parent);
160
161
        foreach ($this->getAssertionIDRef() as $a) {
162
            $a->toXML($e);
163
        }
164
165
        return $e;
166
    }
167
}
168