Skip to content

Commit 8419f77

Browse files
committed
Re-enstate the use of PSR-7 requests
1 parent 93b4c73 commit 8419f77

File tree

10 files changed

+52
-223
lines changed

10 files changed

+52
-223
lines changed

src/SAML2/HTTPRedirect.php

Lines changed: 18 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -120,42 +120,27 @@ public function send(AbstractMessage $message): ResponseInterface
120120
*/
121121
public function receive(ServerRequestInterface $request): AbstractMessage
122122
{
123-
$query = $this->parseQuery();
124-
$signedQuery = $query['SignedQuery'];
125-
126-
/**
127-
* Get the SAMLRequest/SAMLResponse from the exact same signed data that will be verified later in
128-
* validateSignature into $res using the actual SignedQuery
129-
*/
130-
$res = [];
131-
foreach (explode('&', $signedQuery) as $e) {
132-
$tmp = explode('=', $e, 2);
133-
$name = $tmp[0];
134-
if (count($tmp) === 2) {
135-
$value = $tmp[1];
136-
} else {
137-
/* No value for this parameter. */
138-
$value = '';
139-
}
140-
$name = urldecode($name);
141-
$res[$name] = urldecode($value);
142-
}
123+
$query = $request->getQueryParams();
143124

144125
/**
145126
* Put the SAMLRequest/SAMLResponse from the actual query string into $message,
146127
* and assert that the result from parseQuery() in $query and the parsing of the SignedQuery in $res agree
147128
*/
148-
if (array_key_exists('SAMLRequest', $res)) {
149-
Assert::same($res['SAMLRequest'], $query['SAMLRequest'], 'Parse failure.');
150-
$message = $res['SAMLRequest'];
151-
} elseif (array_key_exists('SAMLResponse', $res)) {
152-
Assert::same($res['SAMLResponse'], $query['SAMLResponse'], 'Parse failure.');
153-
$message = $res['SAMLResponse'];
129+
if (array_key_exists('SAMLRequest', $query)) {
130+
$message = urldecode($query['SAMLRequest']);
131+
$signedQuery = 'SAMLRequest=' . $query['SAMLRequest'];
132+
} elseif (array_key_exists('SAMLResponse', $query)) {
133+
$message = urldecode($query['SAMLResponse']);
134+
$signedQuery = 'SAMLResponse=' . $query['SAMLResponse'];
154135
} else {
155136
throw new Exception('Missing SAMLRequest or SAMLResponse parameter.');
156137
}
157138

158-
if (isset($query['SAMLEncoding']) && $query['SAMLEncoding'] !== C::BINDING_HTTP_REDIRECT_DEFLATE) {
139+
if (array_key_exists('SAMLRequest', $query) && array_key_exists('SAMLResponse', $query)) {
140+
throw new Exception('Both SAMLRequest and SAMLResponse provided.');
141+
}
142+
143+
if (isset($query['SAMLEncoding']) && urldecode($query['SAMLEncoding']) !== C::BINDING_HTTP_REDIRECT_DEFLATE) {
159144
throw new Exception(sprintf('Unknown SAMLEncoding: %s', $query['SAMLEncoding']));
160145
}
161146

@@ -174,7 +159,8 @@ public function receive(ServerRequestInterface $request): AbstractMessage
174159
$message = MessageFactory::fromXML($document->documentElement);
175160

176161
if (array_key_exists('RelayState', $query)) {
177-
$this->setRelayState($query['RelayState']);
162+
$this->setRelayState(urldecode($query['RelayState']));
163+
$signedQuery .= '&RelayState=' . $query['RelayState'];
178164
}
179165

180166
if (!array_key_exists('Signature', $query)) {
@@ -192,83 +178,22 @@ public function receive(ServerRequestInterface $request): AbstractMessage
192178

193179
if (!array_key_exists('SigAlg', $query)) {
194180
throw new Exception('Missing signature algorithm.');
181+
} else {
182+
$signedQuery .= '&SigAlg=' . $query['SigAlg'];
195183
}
196184

197185
$container = ContainerSingleton::getInstance();
198186
$blacklist = $container->getBlacklistedEncryptionAlgorithms();
199187
$verifier = (new SignatureAlgorithmFactory($blacklist))->getAlgorithm(
200-
$query['SigAlg'],
188+
urldecode($query['SigAlg']),
201189
// TODO: Need to use the key from the metadata
202190
PEMCertificatesMock::getPublicKey(PEMCertificatesMock::SELFSIGNED_PUBLIC_KEY),
203191
);
204192

205-
if ($verifier->verify($signedQuery, base64_decode($query['Signature'])) === false) {
193+
if ($verifier->verify($signedQuery, base64_decode(urldecode($query['Signature']))) === false) {
206194
throw new SignatureVerificationFailedException('Failed to verify signature.');
207195
}
208196

209197
return $message;
210198
}
211-
212-
213-
/**
214-
* Helper function to parse query data.
215-
*
216-
* This function returns the query string split into key=>value pairs.
217-
* It also adds a new parameter, SignedQuery, which contains the data that is
218-
* signed.
219-
*
220-
* @return array The query data that is signed.
221-
* @throws \Exception
222-
*/
223-
private static function parseQuery(): array
224-
{
225-
/*
226-
* Parse the query string. We need to do this ourself, so that we get access
227-
* to the raw (urlencoded) values. This is required because different software
228-
* can urlencode to different values.
229-
*/
230-
$data = [];
231-
$relayState = '';
232-
$sigAlg = '';
233-
$sigQuery = '';
234-
235-
foreach (explode('&', $_SERVER['QUERY_STRING']) as $e) {
236-
$tmp = explode('=', $e, 2);
237-
$name = $tmp[0];
238-
if (count($tmp) === 2) {
239-
$value = $tmp[1];
240-
} else {
241-
/* No value for this parameter. */
242-
$value = '';
243-
}
244-
245-
$name = urldecode($name);
246-
// Prevent keys from being set more than once
247-
if (array_key_exists($name, $data)) {
248-
throw new Exception('Duplicate parameter.');
249-
}
250-
$data[$name] = urldecode($value);
251-
252-
switch ($name) {
253-
case 'SAMLRequest':
254-
case 'SAMLResponse':
255-
$sigQuery = $name . '=' . $value;
256-
break;
257-
case 'RelayState':
258-
$relayState = '&RelayState=' . $value;
259-
break;
260-
case 'SigAlg':
261-
$sigAlg = '&SigAlg=' . $value;
262-
break;
263-
}
264-
}
265-
266-
if (array_key_exists('SAMLRequest', $data) && array_key_exists('SAMLResponse', $data)) {
267-
throw new Exception('Both SAMLRequest and SAMLResponse provided.');
268-
}
269-
270-
$data['SignedQuery'] = $sigQuery . $relayState . $sigAlg;
271-
272-
return $data;
273-
}
274199
}

src/SAML2/XML/saml/Assertion.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Compat\ContainerSingleton;
1111
use SimpleSAML\SAML2\Constants as C;
1212
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
@@ -262,7 +262,7 @@ public static function fromXML(DOMElement $xml): static
262262
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
263263
$issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
264264

265-
Assert::validDateTimeZulu($issueInstant, ProtocolViolationException::class);
265+
Assert::validDateTime($issueInstant, ProtocolViolationException::class);
266266
$issueInstant = new DateTimeImmutable($issueInstant);
267267

268268
$issuer = Issuer::getChildrenOfClass($xml);

src/SAML2/XML/saml/AuthnStatement.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Constants as C;
1111
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
1212
use SimpleSAML\XML\Exception\InvalidDOMElementException;
@@ -135,15 +135,15 @@ public static function fromXML(DOMElement $xml): static
135135
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
136136
$authnInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $authnInstant, 1);
137137

138-
Assert::validDateTimeZulu($authnInstant, ProtocolViolationException::class);
138+
Assert::validDateTime($authnInstant, ProtocolViolationException::class);
139139
$authnInstant = new DateTimeImmutable($authnInstant);
140140

141141
$sessionNotOnOrAfter = self::getOptionalAttribute($xml, 'SessionNotOnOrAfter', null);
142142
if ($sessionNotOnOrAfter !== null) {
143143
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
144144
$sessionNotOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $sessionNotOnOrAfter, 1);
145145

146-
Assert::validDateTimeZulu($sessionNotOnOrAfter, ProtocolViolationException::class);
146+
Assert::validDateTime($sessionNotOnOrAfter, ProtocolViolationException::class);
147147
$sessionNotOnOrAfter = new DateTimeImmutable($sessionNotOnOrAfter);
148148
}
149149

src/SAML2/XML/saml/Conditions.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Constants as C;
1111
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
1212
use SimpleSAML\XML\Exception\InvalidDOMElementException;
@@ -148,15 +148,15 @@ public static function fromXML(DOMElement $xml): static
148148
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
149149
$notBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $notBefore, 1);
150150

151-
Assert::validDateTimeZulu($notBefore, ProtocolViolationException::class);
151+
Assert::validDateTime($notBefore, ProtocolViolationException::class);
152152
}
153153

154154
$notOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', null);
155155
if ($notOnOrAfter !== null) {
156156
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
157157
$notOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $notOnOrAfter, 1);
158158

159-
Assert::validDateTimeZulu($notOnOrAfter, ProtocolViolationException::class);
159+
Assert::validDateTime($notOnOrAfter, ProtocolViolationException::class);
160160
}
161161

162162
$condition = AbstractCondition::getChildrenOfClass($xml);

src/SAML2/XML/saml/SubjectConfirmationData.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Constants as C;
1111
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
1212
use SimpleSAML\SAML2\Utils;
@@ -168,7 +168,7 @@ public static function fromXML(DOMElement $xml): static
168168
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
169169
$NotBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotBefore, 1);
170170

171-
Assert::validDateTimeZulu($NotBefore, ProtocolViolationException::class);
171+
Assert::validDateTime($NotBefore, ProtocolViolationException::class);
172172
$NotBefore = new DateTimeImmutable($NotBefore);
173173
}
174174

@@ -177,7 +177,7 @@ public static function fromXML(DOMElement $xml): static
177177
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
178178
$NotOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotOnOrAfter, 1);
179179

180-
Assert::validDateTimeZulu($NotOnOrAfter, ProtocolViolationException::class);
180+
Assert::validDateTime($NotOnOrAfter, ProtocolViolationException::class);
181181
$NotOnOrAfter = new DateTimeImmutable($NotOnOrAfter);
182182
}
183183

src/SAML2/XML/samlp/AbstractMessage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use DateTimeImmutable;
88
use DOMDocument;
99
use DOMElement;
10-
use SimpleSAML\Assert\Assert;
10+
use SimpleSAML\XML\Assert\Assert;
1111
use SimpleSAML\SAML2\Compat\ContainerSingleton;
1212
use SimpleSAML\SAML2\Constants as C;
1313
use SimpleSAML\SAML2\Exception\ProtocolViolationException;

src/SAML2/XML/samlp/AbstractStatusResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Constants as C;
1111
use SimpleSAML\SAML2\XML\saml\Issuer;
1212

src/SAML2/XML/samlp/AuthnRequest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
1111
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
1212
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
@@ -252,7 +252,7 @@ public static function fromXML(DOMElement $xml): static
252252
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
253253
$issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
254254

255-
Assert::validDateTimeZulu($issueInstant, ProtocolViolationException::class);
255+
Assert::validDateTime($issueInstant, ProtocolViolationException::class);
256256
$issueInstant = new DateTimeImmutable($issueInstant);
257257

258258
$attributeConsumingServiceIndex = self::getOptionalIntegerAttribute(

src/SAML2/XML/samlp/Response.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DateTimeImmutable;
88
use DOMElement;
9-
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Assert\Assert;
1010
use SimpleSAML\SAML2\Constants as C;
1111
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
1212
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
@@ -118,7 +118,7 @@ public static function fromXML(DOMElement $xml): static
118118
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
119119
$issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
120120

121-
Assert::validDateTimeZulu($issueInstant, ProtocolViolationException::class);
121+
Assert::validDateTime($issueInstant, ProtocolViolationException::class);
122122
$issueInstant = new DateTimeImmutable($issueInstant);
123123

124124
$issuer = Issuer::getChildrenOfClass($xml);

0 commit comments

Comments
 (0)