Skip to content

Commit f2399fa

Browse files
authored
Merge commit from fork
1 parent d58906e commit f2399fa

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

src/webauthn/src/CeremonyStep/CheckAllowedOrigins.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,15 @@ public function __construct(
3434
array $allowedOrigins,
3535
private bool $allowSubdomains = false
3636
) {
37-
$origins = [];
3837
foreach ($allowedOrigins as $allowedOrigin) {
3938
$parsedAllowedOrigin = parse_url($allowedOrigin);
4039
$parsedAllowedOrigin !== false || throw new InvalidArgumentException(sprintf(
4140
'Invalid origin: %s',
4241
$allowedOrigin
4342
));
44-
$allowedOriginHost = $parsedAllowedOrigin['host'] ?? '';
45-
if ($allowedOriginHost === '') {
46-
$allowedOriginHost = $allowedOrigin;
47-
}
48-
$origins[] = $allowedOriginHost;
4943
}
5044

51-
$this->allowedOrigins = array_unique($origins);
45+
$this->allowedOrigins = array_unique($allowedOrigins);
5246
}
5347

5448
public function process(
@@ -77,10 +71,14 @@ public function process(
7771
is_array($parsedRelyingPartyId) || throw AuthenticatorResponseVerificationException::create(
7872
'Invalid origin. Unable to parse the origin.'
7973
);
80-
if (in_array($clientDataRpId, $this->allowedOrigins, true)) {
74+
if (in_array($C->origin, $this->allowedOrigins, true)) {
8175
return;
8276
}
83-
$isSubDomain = $this->isSubdomain($this->allowedOrigins, $clientDataRpId);
77+
$allowedHosts = array_map(
78+
static fn (string $origin): string => parse_url($origin, PHP_URL_HOST) ?? $origin,
79+
$this->allowedOrigins
80+
);
81+
$isSubDomain = $this->isSubdomain($allowedHosts, $clientDataRpId);
8482
if ($this->allowSubdomains && $isSubDomain) {
8583
return;
8684
}

tests/library/Functional/CheckAllowedOriginsTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,67 @@ public function emptyAllowedOriginsWithSubdomainsAndInvalidHost(): void
217217
);
218218
}
219219

220+
#[Test]
221+
public function differentPortShouldBeRejected(): void
222+
{
223+
// Then
224+
$this->expectException(AuthenticatorResponseVerificationException::class);
225+
$this->expectExceptionMessage('Invalid origin');
226+
227+
// Given
228+
$checkOrigins = new CheckAllowedOrigins(['https://login.example.com:8443']);
229+
$publicKeyCredentialSource = $this->getPublicKeyCredentialSource();
230+
$publicKeyCredentialRequestOptions = $this->getPublicKeyCredentialRequestOptions();
231+
$publicKeyCredential = $this->createPublicKeyCredentialWithOrigin('https://login.example.com');
232+
233+
// When
234+
$checkOrigins->process(
235+
$publicKeyCredentialSource,
236+
$publicKeyCredential->response,
237+
$publicKeyCredentialRequestOptions,
238+
null,
239+
'login.example.com',
240+
);
241+
}
242+
243+
#[Test]
244+
public function differentSchemeShouldBeRejected(): void
245+
{
246+
// Then
247+
$this->expectException(AuthenticatorResponseVerificationException::class);
248+
$this->expectExceptionMessage('Invalid origin');
249+
250+
// Given
251+
$checkOrigins = new CheckAllowedOrigins(['http://login.example.com']);
252+
$publicKeyCredentialSource = $this->getPublicKeyCredentialSource();
253+
$publicKeyCredentialRequestOptions = $this->getPublicKeyCredentialRequestOptions();
254+
$publicKeyCredential = $this->createPublicKeyCredentialWithOrigin('https://login.example.com');
255+
256+
// When
257+
$checkOrigins->process(
258+
$publicKeyCredentialSource,
259+
$publicKeyCredential->response,
260+
$publicKeyCredentialRequestOptions,
261+
null,
262+
'login.example.com',
263+
);
264+
}
265+
266+
private function createPublicKeyCredentialWithOrigin(string $origin): PublicKeyCredential
267+
{
268+
$clientDataJson = json_encode([
269+
'origin' => $origin,
270+
'challenge' => '8hPZ5agbQx6bCw_X9c75JyE3DP1PAvW1wv3WknpqBhc',
271+
'type' => 'webauthn.create',
272+
], JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES);
273+
$clientDataJsonB64 = rtrim(strtr(base64_encode($clientDataJson), '+/', '-_'), '=');
274+
275+
$json = '{"id":"12Q1ykFsRWcUbO_y23o3cimk9Bn3rFahaKEAUHyMjrg","rawId":"12Q1ykFsRWcUbO_y23o3cimk9Bn3rFahaKEAUHyMjrg","response":{"attestationObject":"o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEgwRgIhAIVT1JJcjJlU4xyiEWB1DO3OqMLJdC62t8es-JvwbDTgAiEA4E9bIHL-bq4_r09qUBDcm-qCqz0a7NP42K_fSj1YoqBjeDVjglkCkjCCAo4wggI0oAMCAQICAQEwCgYIKoZIzj0EAwIwga8xJjAkBgNVBAMMHUZJRE8yIElOVEVSTUVESUFURSBwcmltZTI1NnYxMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMQwwCgYDVQQLDANDV0cxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNWTESMBAGA1UEBwwJV2FrZWZpZWxkMB4XDTE4MDUyMzE0Mzc0MVoXDTI4MDUyMDE0Mzc0MVowgcIxIzAhBgNVBAMMGkZJRE8yIEJBVENIIEtFWSBwcmltZTI1NnYxMTEwLwYJKoZIhvcNAQkBFiJjb25mb3JtYW5jZS10b29sc0BmaWRvYWxsaWFuY2Uub3JnMRYwFAYDVQQKDA1GSURPIEFsbGlhbmNlMSIwIAYDVQQLDBlBdXRoZW50aWNhdG9yIEF0dGVzdGF0aW9uMQswCQYDVQQGEwJVUzELMAkGA1UECAwCTVkxEjAQBgNVBAcMCVdha2VmaWVsZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLrZYqzxrVIvmvsKDJIcF9vrOpmT0KSjZmO-xPXL8hr7gGRpZRxRkYP0fJEPzCo0ZTK3D-vHFtsdDgG9V24pSGSjLDAqMAkGA1UdEwQCMAAwHQYDVR0OBBYEFEpU5QbSkURPbQ8zXdb9x0ZsuV9UMAoGCCqGSM49BAMCA0gAMEUCIQC5Wza0c32jrBDTDb7165XlBCdCWkSVfzvhhqHTfyfqRQIgTQuswDhApHwqT_X6W8aYccqenKb9HKF8DNaRhHM3KXhZBDUwggQxMIICGaADAgECAgECMA0GCSqGSIb3DQEBCwUAMIGhMRgwFgYDVQQDDA9GSURPMiBURVNUIFJPT1QxMTAvBgkqhkiG9w0BCQEWImNvbmZvcm1hbmNlLXRvb2xzQGZpZG9hbGxpYW5jZS5vcmcxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxDDAKBgNVBAsMA0NXRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1ZMRIwEAYDVQQHDAlXYWtlZmllbGQwHhcNMTgwNzIzMTQyOTA3WhcNNDUxMjA4MTQyOTA3WjCBrzEmMCQGA1UEAwwdRklETzIgSU5URVJNRURJQVRFIHByaW1lMjU2djExMTAvBgkqhkiG9w0BCQEWImNvbmZvcm1hbmNlLXRvb2xzQGZpZG9hbGxpYW5jZS5vcmcxFjAUBgNVBAoMDUZJRE8gQWxsaWFuY2UxDDAKBgNVBAsMA0NXRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1ZMRIwEAYDVQQHDAlXYWtlZmllbGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATcQR3fVW1_TXOMqXUUelVx9GMAKSPWb7R7XpeHIHBZBQ7JzoepbzRXitTdCLTCfNXpLE1G6JRcstPmX9tLSXnzoy8wLTAMBgNVHRMEBTADAQH_MB0GA1UdDgQWBBRnwRmSkFv1XQDB1iEOjC12IZJHwDANBgkqhkiG9w0BAQsFAAOCAgEAC5gup7NUuwcndifv5dwlZ6GISPTEciQdMxmNo9nE9BRAO2btQ0DdJdifA8GnQQd29dIgk8U48WucY4qzuvRZaK6z6AIrU2bAUlJrKnlTZvjdiM3oiTY9WTiB9eyfmK_ZgEv7W9DEFW7vrh32-pjSNF1VyxuMEpna1X6syqtNDVG-w0YLjdkXi0ciuRJy0Q9A90vmMKgAxgnRfCol5aQUlHpZMTiK-8OCp8sSoq05QN39iy34u4AeKGUWeuKjYEwNsgKgn-v1-A1dbUw2cWYg53Oi5m_DQLlt-Ws1hokuwXxCekaBvieB9nu13fYXv7SkgwuWPNwyFPlQkWpIPgb9eZME3knUiJ2EAS1UE7kraWNg3cQO2v6tY24-5-FmEyuWinGChrHswT0sYtmhQGlWa0bCV9fELL69bCO64RiWoenLsiX15hmmC7-ZbF9D1VHj1BHR9eioAZUVonEiDJSZHtVxXlmU3jQBhrEPztF5Rn670dzq_E4HLPfzbrKW-L2F2i-WEWF7cticNVBBLXUHsFAvGYMqv7DE0zDGaZ7L-jXIjSCiE2IjixChMYw_aFYwmx0N6yuXeJDYu8fCSXOKTPR6ZRsLCQ38tXFSQRyn1T5Fgvxds7Q2sxgtVXCNy8FMoof27gjMu5i4pAt2ldXEOx1zI2P-Nv6GFxY2U_BtXINoYXV0aERhdGFYpJYE6oKCTpikraFLRGLQ1zqOxGkTDakbGTB0WSKfdKNZQQAAABuA9T0ehS5D7bs_0C8TIuWvACDXZDXKQWxFZxRs7_LbejdyKaT0GfesVqFooQBQfIyOuKUBAgMmIAEhWCCR3V4iMssbPhNCS1rk4wtdZKaqX9L5e3DwGUJKi0OBgCJYIKBBtvFMQHD3m-EgmcQOXmQhctxiyh68RT1QmNq_xWm4","clientDataJSON":"' . $clientDataJsonB64 . '"},"getClientExtensionResults":{},"type":"public-key"}';
276+
277+
return $this->getSerializer()
278+
->deserialize($json, PublicKeyCredential::class, 'json');
279+
}
280+
220281
private function getPublicKeyCredentialSource(): PublicKeyCredentialSource
221282
{
222283
return $this->createPublicKeyCredentialSource(

0 commit comments

Comments
 (0)