Skip to content

Commit 4f8fd3c

Browse files
committed
Add NameIDMappingRequest-element
1 parent 8447f62 commit 4f8fd3c

13 files changed

+284
-15
lines changed

src/XML/IdentifierTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ trait IdentifierTrait
3232
/**
3333
* Collect the value of the identifier-property
3434
*
35-
* @return \SimpleSAML\SAML2\XML\saml\IdentifierInterface|null
35+
* @return (\SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface)|null
3636
*/
3737
public function getIdentifier(): ?IdentifierInterface
3838
{

src/XML/saml/Subject.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ public function toXML(?DOMElement $parent = null): DOMElement
9696
{
9797
$e = $this->instantiateParentElement($parent);
9898

99-
/** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */
100-
$identifier = $this->getIdentifier();
101-
$identifier?->toXML($e);
99+
$this->getIdentifier()?->toXML($e);
102100

103101
foreach ($this->getSubjectConfirmation() as $sc) {
104102
$sc->toXML($e);

src/XML/saml/SubjectConfirmation.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ public function toXML(?DOMElement $parent = null): DOMElement
103103
$e = $this->instantiateParentElement($parent);
104104
$e->setAttribute('Method', $this->getMethod()->getValue());
105105

106-
/** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */
107-
$identifier = $this->getIdentifier();
108-
$identifier?->toXML($e);
106+
$this->getIdentifier()?->toXML($e);
109107

110108
if ($this->getSubjectConfirmationData() !== null && !$this->getSubjectConfirmationData()->isEmptyElement()) {
111109
$this->getSubjectConfirmationData()->toXML($e);

src/XML/samlp/AbstractMessage.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace SimpleSAML\SAML2\XML\samlp;
66

77
use DOMElement;
8-
use SimpleSAML\SAML2\Constants as C;
98
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
109
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
1110
use SimpleSAML\SAML2\Utils\XPath;
@@ -47,8 +46,8 @@ abstract class AbstractMessage extends AbstractSamlpElement implements SignableE
4746
/**
4847
* Initialize a message.
4948
*
50-
* @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
5149
* @param \SimpleSAML\XMLSchema\Type\IDValue $id
50+
* @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
5251
* @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $issueInstant
5352
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination
5453
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent
@@ -177,7 +176,7 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
177176
$root->setAttribute('Destination', $this->getDestination()->getValue());
178177
}
179178

180-
if ($this->getConsent() !== null && $this->getConsent()->getValue() !== C::CONSENT_UNSPECIFIED) {
179+
if ($this->getConsent() !== null) {
181180
$root->setAttribute('Consent', $this->getConsent()->getValue());
182181
}
183182

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\SAML2\XML\samlp;
6+
7+
use DOMElement;
8+
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
9+
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
10+
use SimpleSAML\SAML2\XML\IdentifierTrait;
11+
use SimpleSAML\SAML2\XML\saml\IdentifierInterface;
12+
use SimpleSAML\SAML2\XML\saml\Issuer;
13+
use SimpleSAML\SAML2\XML\samlp\NameIDPolicy;
14+
use SimpleSAML\XMLSchema\Type\IDValue;
15+
16+
/**
17+
* Class representing the samlp:NameIDMappingRequestType.
18+
*
19+
* @package simplesamlphp/saml2
20+
*/
21+
abstract class AbstractNameIDMappingRequest extends AbstractRequest
22+
{
23+
use IdentifierTrait;
24+
25+
26+
/**
27+
* Initialize a NameIDMappingRequest.
28+
*
29+
* @param \SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier
30+
* @param \SimpleSAML\SAML2\XML\samlp\NameIDPolicy $nameIdPolicy
31+
* @param \SimpleSAML\XMLSchema\Type\IDValue $id
32+
* @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
33+
* @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $issueInstant
34+
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination
35+
* @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent
36+
* @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions
37+
*/
38+
final public function __construct(
39+
IdentifierInterface $identifier,
40+
protected NameIDPolicy $nameIdPolicy,
41+
IDValue $id,
42+
?Issuer $issuer = null,
43+
?SAMLDateTimeValue $issueInstant = null,
44+
?SAMLAnyURIValue $destination = null,
45+
?SAMLAnyURIValue $consent = null,
46+
?Extensions $extensions = null,
47+
) {
48+
$this->setIdentifier($identifier);
49+
50+
parent::__construct($id, $issuer, $issueInstant, $destination, $consent, $extensions);
51+
}
52+
53+
54+
/**
55+
* Retrieve the NameIDPolicy of this element.
56+
*
57+
* @return \SimpleSAML\SAML2\XML\samlp\NameIDPolicy
58+
*/
59+
public function getNameIDPolicy(): NameIDPolicy
60+
{
61+
return $this->nameIdPolicy;
62+
}
63+
64+
65+
/**
66+
* Convert this NameIDMappingRequest to XML
67+
*/
68+
public function toUnsignedXML(?DOMElement $parent = null): DOMElement
69+
{
70+
$e = parent::toUnsignedXML($parent);
71+
72+
$this->getIdentifier()->toXML($e);
73+
$this->getNameIDPolicy()->toXML($e);
74+
75+
return $e;
76+
}
77+
}

src/XML/samlp/LogoutRequest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,7 @@ protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
199199
$e->setAttribute('Reason', $this->getReason()->getValue());
200200
}
201201

202-
/** @var \SimpleSAML\XML\SerializableElementInterface&\SimpleSAML\SAML2\XML\saml\IdentifierInterface $identifier */
203-
$identifier = $this->getIdentifier();
204-
$identifier->toXML($e);
202+
$this->getIdentifier()->toXML($e);
205203

206204
foreach ($this->getSessionIndexes() as $sessionIndex) {
207205
$sessionIndex->toXML($e);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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;
10+
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
11+
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
12+
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
13+
use SimpleSAML\SAML2\Type\SAMLStringValue;
14+
use SimpleSAML\SAML2\XML\saml\Issuer;
15+
use SimpleSAML\XML\SchemaValidatableElementInterface;
16+
use SimpleSAML\XML\SchemaValidatableElementTrait;
17+
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
18+
use SimpleSAML\XMLSchema\Exception\MissingElementException;
19+
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
20+
use SimpleSAML\XMLSchema\Type\IDValue;
21+
use SimpleSAML\XMLSecurity\XML\ds\Signature;
22+
23+
use function array_pop;
24+
use function version_compare;
25+
26+
/**
27+
* Class for handling SAML2 NameIDMappingRequest.
28+
*
29+
* @package simplesamlphp/saml2
30+
*/
31+
final class NameIDMappingRequest extends AbstractNameIDMappingRequest implements
32+
SchemaValidatableElementInterface
33+
{
34+
use SchemaValidatableElementTrait;
35+
36+
37+
/**
38+
* Convert XML into a NameIDMappingRequest
39+
*
40+
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
41+
* if the qualified name of the supplied element is wrong
42+
*/
43+
public static function fromXML(DOMElement $xml): static
44+
{
45+
Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
46+
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
47+
48+
$version = self::getAttribute($xml, 'Version', SAMLStringValue::class);
49+
Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class);
50+
Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class);
51+
52+
$issuer = Issuer::getChildrenOfClass($xml);
53+
Assert::maxCount($issuer, 1, 'Only one <saml:Issuer> element is allowed.', TooManyElementsException::class);
54+
55+
$extensions = Extensions::getChildrenOfClass($xml);
56+
Assert::maxCount(
57+
$extensions,
58+
1,
59+
'Only one <samlp:Extensions> element is allowed.',
60+
TooManyElementsException::class,
61+
);
62+
63+
$signature = Signature::getChildrenOfClass($xml);
64+
Assert::maxCount(
65+
$signature,
66+
1,
67+
'Only one <ds:Signature> element is allowed.',
68+
TooManyElementsException::class,
69+
);
70+
71+
$nameIdPolicy = NameIDPolicy::getChildrenOfClass($xml);
72+
Assert::minCount($nameIdPolicy, 1, MissingElementException::class);
73+
Assert::maxCount($nameIdPolicy, 1, TooManyElementsException::class);
74+
75+
$request = new static(
76+
self::getIdentifierFromXML($xml),
77+
array_pop($nameIdPolicy),
78+
self::getAttribute($xml, 'ID', IDValue::class),
79+
array_pop($issuer),
80+
self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class),
81+
self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null),
82+
self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null),
83+
array_pop($extensions),
84+
);
85+
86+
if (!empty($signature)) {
87+
$request->setSignature($signature[0]);
88+
$request->messageContainedSignatureUponConstruction = true;
89+
$request->setXML($xml);
90+
}
91+
92+
return $request;
93+
}
94+
}

tests/SAML2/XML/samlp/AuthnRequestTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public function testMarshalling(): void
106106
issuer: new Issuer(
107107
SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'),
108108
),
109+
consent: SAMLAnyURIValue::fromString(C::CONSENT_UNSPECIFIED),
109110
id: IDValue::fromString('_2b0226190ca1c22de6f66e85f5c95158'),
110111
issueInstant: SAMLDateTimeValue::fromString('2014-09-22T13:42:00Z'),
111112
destination: SAMLAnyURIValue::fromString('https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO'),

tests/SAML2/XML/samlp/LogoutRequestTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Psr\Clock\ClockInterface;
1111
use SimpleSAML\SAML2\Compat\ContainerSingleton;
1212
use SimpleSAML\SAML2\Constants as C;
13+
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
1314
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
1415
use SimpleSAML\SAML2\Type\SAMLStringValue;
1516
use SimpleSAML\SAML2\Utils;
@@ -80,6 +81,7 @@ public function testMarshalling(): void
8081

8182
$logoutRequest = new LogoutRequest(
8283
id: IDValue::fromString('SomeIDValue'),
84+
consent: SAMLAnyURIValue::fromString(C::CONSENT_UNSPECIFIED),
8385
identifier: $nameId,
8486
issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()),
8587
sessionIndexes: [
@@ -106,6 +108,7 @@ public function testMarshalling(): void
106108
);
107109
$logoutRequest = new LogoutRequest(
108110
id: IDValue::fromString('SomeIDValue'),
111+
consent: SAMLAnyURIValue::fromString(C::CONSENT_UNSPECIFIED),
109112
identifier: $nameId,
110113
issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()),
111114
sessionIndexes: [
@@ -133,6 +136,7 @@ public function testMarshallingElementOrdering(): void
133136

134137
$logoutRequest = new LogoutRequest(
135138
id: IDValue::fromString('SomeIDValue'),
139+
consent: SAMLAnyURIValue::fromString(C::CONSENT_UNSPECIFIED),
136140
identifier: $nameId,
137141
issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()),
138142
sessionIndexes: [
@@ -201,6 +205,7 @@ public function testEncryptedNameId(): void
201205

202206
$logoutRequest = new LogoutRequest(
203207
identifier: $eid,
208+
consent: SAMLAnyURIValue::fromString(C::CONSENT_UNSPECIFIED),
204209
id: IDValue::fromString('SomeIDValue'),
205210
issueInstant: SAMLDateTimeValue::fromDateTime(self::$clock->now()),
206211
);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\SAML2\XML\samlp;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\Group;
9+
use PHPUnit\Framework\TestCase;
10+
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
11+
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
12+
use SimpleSAML\SAML2\Type\SAMLStringValue;
13+
use SimpleSAML\SAML2\XML\saml\Issuer;
14+
use SimpleSAML\SAML2\XML\saml\NameID;
15+
use SimpleSAML\SAML2\XML\samlp\AbstractMessage;
16+
use SimpleSAML\SAML2\XML\samlp\AbstractRequest;
17+
use SimpleSAML\SAML2\XML\samlp\AbstractSamlpElement;
18+
use SimpleSAML\SAML2\XML\samlp\NameIDMappingRequest;
19+
use SimpleSAML\SAML2\XML\samlp\NameIDPolicy;
20+
use SimpleSAML\XML\DOMDocumentFactory;
21+
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
22+
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
23+
use SimpleSAML\XMLSchema\Type\BooleanValue;
24+
use SimpleSAML\XMLSchema\Type\IDValue;
25+
26+
use function dirname;
27+
use function strval;
28+
29+
/**
30+
* Class \SimpleSAML\SAML2\XML\samlp\NameIDMappingRequestTest
31+
*
32+
* @package simplesamlphp/saml2
33+
*/
34+
#[Group('saml')]
35+
#[CoversClass(NameIDMappingRequest::class)]
36+
#[CoversClass(AbstractRequest::class)]
37+
#[CoversClass(AbstractMessage::class)]
38+
#[CoversClass(AbstractSamlpElement::class)]
39+
final class NameIDMappingRequestTest extends TestCase
40+
{
41+
use SchemaValidationTestTrait;
42+
use SerializableElementTestTrait;
43+
44+
45+
/**
46+
*/
47+
public static function setUpBeforeClass(): void
48+
{
49+
self::$testedClass = NameIDMappingRequest::class;
50+
51+
self::$xmlRepresentation = DOMDocumentFactory::fromFile(
52+
dirname(__FILE__, 4) . '/resources/xml/samlp_NameIDMappingRequest.xml',
53+
);
54+
}
55+
56+
57+
// marshalling
58+
59+
60+
/**
61+
*/
62+
public function testMarshalling(): void
63+
{
64+
$nameId = new NameID(
65+
SAMLStringValue::fromString('TheNameIDValue'),
66+
SAMLStringValue::fromString('urn:x-simplesamlphp:namequalifier'),
67+
SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'),
68+
SAMLAnyURIValue::fromString('urn:the:format'),
69+
SAMLStringValue::fromString('TheSPProvidedID'),
70+
);
71+
72+
$nameIdPolicy = new NameIDPolicy(
73+
SAMLAnyURIValue::fromString('urn:the:format'),
74+
SAMLStringValue::fromString('urn:x-simplesamlphp:spnamequalifier'),
75+
BooleanValue::fromBoolean(true),
76+
);
77+
78+
$nameIdMappingRequest = new NameIDMappingRequest(
79+
identifier: $nameId,
80+
nameIdPolicy: $nameIdPolicy,
81+
issuer: new Issuer(
82+
SAMLStringValue::fromString('https://gateway.stepup.org/saml20/sp/metadata'),
83+
),
84+
id: IDValue::fromString('_2b0226190ca1c22de6f66e85f5c95158'),
85+
issueInstant: SAMLDateTimeValue::fromString('2014-09-22T13:42:00Z'),
86+
destination: SAMLAnyURIValue::fromString('https://tiqr.stepup.org/idp/profile/saml2/Redirect/SSO'),
87+
);
88+
89+
$this->assertEquals(
90+
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
91+
strval($nameIdMappingRequest),
92+
);
93+
}
94+
}

0 commit comments

Comments
 (0)