@@ -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