From 4a0497e27c82c5f6f44d9a570d5bcbc8930fe1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Wed, 22 Nov 2023 16:50:56 +0000 Subject: [PATCH 1/2] Fix Detected invalid UTF-8 for field... issue when storing session data from Webauthn in a mongo database --- CHANGELOG.md | 3 +++ src/Webauthn/AuthenticateAdapter.php | 6 ++++-- src/Webauthn/RegisterAdapter.php | 6 ++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd799ce97..cd67206d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Changelog ========= Releases for CakePHP 4.5 ------------------------ +* 11.3.4 + * Fix `Detected invalid UTF-8 for field...` issue when storing session data from `Webauthn` in a mongo database. + * 11.3.3 * Add display of unauthorized url in flash message when debug is true diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php index 592c9590a..e899cad43 100644 --- a/src/Webauthn/AuthenticateAdapter.php +++ b/src/Webauthn/AuthenticateAdapter.php @@ -34,7 +34,7 @@ public function getOptions(): PublicKeyCredentialRequestOptions ); $this->request->getSession()->write( 'Webauthn2fa.authenticateOptions', - $options + json_encode($options) ); return $options; @@ -47,7 +47,9 @@ public function getOptions(): PublicKeyCredentialRequestOptions */ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource { - $options = $this->request->getSession()->read('Webauthn2fa.authenticateOptions'); + $options = PublicKeyCredentialRequestOptions::createFromString( + (string)$this->request->getSession()->read('Webauthn2fa.authenticateOptions') + ); return $this->loadAndCheckAssertionResponse($options); } diff --git a/src/Webauthn/RegisterAdapter.php b/src/Webauthn/RegisterAdapter.php index c28b0504a..a4ef2a1f1 100644 --- a/src/Webauthn/RegisterAdapter.php +++ b/src/Webauthn/RegisterAdapter.php @@ -28,7 +28,7 @@ public function getOptions(): PublicKeyCredentialCreationOptions PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, [] ); - $this->request->getSession()->write('Webauthn2fa.registerOptions', $options); + $this->request->getSession()->write('Webauthn2fa.registerOptions', json_encode($options)); $this->request->getSession()->write('Webauthn2fa.userEntity', $userEntity); return $options; @@ -41,7 +41,9 @@ public function getOptions(): PublicKeyCredentialCreationOptions */ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource { - $options = $this->request->getSession()->read('Webauthn2fa.registerOptions'); + $options = PublicKeyCredentialCreationOptions::createFromString( + (string)$this->request->getSession()->read('Webauthn2fa.registerOptions') + ); $credential = $this->loadAndCheckAttestationResponse($options); $this->repository->saveCredentialSource($credential); From 60515d83280ccd9594ca5c9b402fdd67ef1efcdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20P=C3=A9rez?= Date: Wed, 22 Nov 2023 17:16:07 +0000 Subject: [PATCH 2/2] Fux webauthn tests --- src/Webauthn/AuthenticateAdapter.php | 1 + src/Webauthn/RegisterAdapter.php | 1 + tests/TestCase/Webauthn/AuthenticateAdapterTest.php | 2 +- tests/TestCase/Webauthn/RegisterAdapterTest.php | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php index e899cad43..24cd2965f 100644 --- a/src/Webauthn/AuthenticateAdapter.php +++ b/src/Webauthn/AuthenticateAdapter.php @@ -47,6 +47,7 @@ public function getOptions(): PublicKeyCredentialRequestOptions */ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource { + /** @var \Webauthn\PublicKeyCredentialRequestOptions $options */ $options = PublicKeyCredentialRequestOptions::createFromString( (string)$this->request->getSession()->read('Webauthn2fa.authenticateOptions') ); diff --git a/src/Webauthn/RegisterAdapter.php b/src/Webauthn/RegisterAdapter.php index a4ef2a1f1..283bc85ac 100644 --- a/src/Webauthn/RegisterAdapter.php +++ b/src/Webauthn/RegisterAdapter.php @@ -41,6 +41,7 @@ public function getOptions(): PublicKeyCredentialCreationOptions */ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource { + /** @var \Webauthn\PublicKeyCredentialCreationOptions $options */ $options = PublicKeyCredentialCreationOptions::createFromString( (string)$this->request->getSession()->read('Webauthn2fa.registerOptions') ); diff --git a/tests/TestCase/Webauthn/AuthenticateAdapterTest.php b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php index 70c101c90..83773530d 100644 --- a/tests/TestCase/Webauthn/AuthenticateAdapterTest.php +++ b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php @@ -36,7 +36,7 @@ public function testGetOptions() $adapter = new AuthenticateAdapter($request); $options = $adapter->getOptions(); $this->assertInstanceOf(PublicKeyCredentialRequestOptions::class, $options); - $this->assertSame($options, $request->getSession()->read('Webauthn2fa.authenticateOptions')); + $this->assertSame(json_encode($options), $request->getSession()->read('Webauthn2fa.authenticateOptions')); $data = json_decode('{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA","signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL","userHandle":"","clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"},"type":"public-key"}', true); $request = $request->withParsedBody($data); diff --git a/tests/TestCase/Webauthn/RegisterAdapterTest.php b/tests/TestCase/Webauthn/RegisterAdapterTest.php index 3ce86a8e8..e2fe93510 100644 --- a/tests/TestCase/Webauthn/RegisterAdapterTest.php +++ b/tests/TestCase/Webauthn/RegisterAdapterTest.php @@ -37,7 +37,7 @@ public function testGetOptions() $this->assertFalse($adapter->hasCredential()); $options = $adapter->getOptions(); $this->assertInstanceOf(PublicKeyCredentialCreationOptions::class, $options); - $this->assertSame($options, $request->getSession()->read('Webauthn2fa.registerOptions')); + $this->assertSame(json_encode($options), $request->getSession()->read('Webauthn2fa.registerOptions')); $data = '{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"},"type":"public-key"}'; $request = $request->withParsedBody(