From 292fe64e7883e74a63293f28806725411eedb3be Mon Sep 17 00:00:00 2001
From: phpipam <miha.petkovsek@telemach.si>
Date: Thu, 14 Dec 2023 14:26:09 +0100
Subject: [PATCH] Updated passkeys

---
 app/login/passkey_login_check.php             |  8 +-
 app/tools/user-menu/passkey_save.php          | 86 +++++++++++--------
 app/tools/user-menu/passkeys.php              | 16 ++--
 functions/composer.json                       |  3 +-
 functions/composer.lock                       | 10 +--
 functions/vendor/autoload.php                 |  2 +-
 functions/vendor/composer/autoload_real.php   |  8 +-
 functions/vendor/composer/autoload_static.php |  8 +-
 functions/vendor/composer/installed.json      |  8 +-
 functions/vendor/composer/installed.php       |  6 +-
 functions/vendor/firehed/webauthn             |  2 +-
 11 files changed, 82 insertions(+), 75 deletions(-)

diff --git a/app/login/passkey_login_check.php b/app/login/passkey_login_check.php
index c955cfbb..58cdadec 100644
--- a/app/login/passkey_login_check.php
+++ b/app/login/passkey_login_check.php
@@ -29,6 +29,7 @@ use Firehed\WebAuthn\{
     SessionChallengeManager,
     SingleOriginRelyingParty,
     ResponseParser,
+    ArrayBufferResponseParser,
     BinaryString
 };
 
@@ -37,14 +38,9 @@ $json = file_get_contents('php://input');
 $data = json_decode($json, true);
 
 // parser
-$parser = new ResponseParser();
+$parser = new ArrayBufferResponseParser();
 $getResponse = $parser->parseGetResponse($data);
 
-// header('HTTP/1.1 201 Created');
-// header('Content-Type: text/html; charset=utf-8');
-// echo(implode('', array_map('chr', $data['keyId'])));
-// die();
-
 // Set relaying party
 $rp = new \Firehed\WebAuthn\SingleOriginRelyingParty($User->createURL ());
 // challange manager
diff --git a/app/tools/user-menu/passkey_save.php b/app/tools/user-menu/passkey_save.php
index 0be8bbc6..a37d70cf 100644
--- a/app/tools/user-menu/passkey_save.php
+++ b/app/tools/user-menu/passkey_save.php
@@ -27,45 +27,59 @@ use Firehed\WebAuthn\{
     RelyingParty,
     SessionChallengeManager,
     SingleOriginRelyingParty,
-    JsonResponseParser
+    JsonResponseParser,
+    ArrayBufferResponseParser
 };
 
 # process request
 $json = file_get_contents('php://input');
 $data = json_decode($json, true);
 
-// parser
-$parser = new JsonResponseParser();
-$createResponse = $parser->parseCreateResponse($data);
-
-// escape keyId
-$data['keyId'] =  $User->strip_input_tags ($data['keyId']);
-
-// Relaying party
-$rp = new \Firehed\WebAuthn\SingleOriginRelyingParty($User->createURL ());
-// challange manager
-$challengeManager = new \Firehed\WebAuthn\SessionChallengeManager();
-
-// Verify credentials, if it fails exit
-try {
-    $credential = $createResponse->verify($challengeManager, $rp);
-} catch (Throwable) {
-    header('HTTP/1.1 403 Unauthorized');
-    return;
-}
-
-// encode credentials to store to database
-$codec = new Codecs\Credential();
-$encodedCredential = $codec->encode($credential);
-
-
-// save passkey
-$User->save_passkey ($encodedCredential, $credential->getStorageId(), $data['keyId']);
-
-// print result
-header('HTTP/1.1 200 OK');
-header('Content-type: application/json');
-echo json_encode([
-        'success' => true,
-        'credentialId' => $credential->getStorageId()
-]);
\ No newline at end of file
+//
+// we dont try to catch exceptions, as messages are unclear, check webserver/php-fpm error_logs
+//
+
+// try {
+    // parser
+    $parser = new ArrayBufferResponseParser();
+    $createResponse = $parser->parseCreateResponse($data);
+
+    // escape keyId
+    $data['keyId'] = $User->strip_input_tags ($data['keyId']);
+
+    // Relaying party
+    $rp = new \Firehed\WebAuthn\SingleOriginRelyingParty($User->createURL ());
+    // challange manager
+    $challengeManager = new \Firehed\WebAuthn\SessionChallengeManager();
+
+    // Verify credentials, if it fails exit
+    try {
+        $credential = $createResponse->verify($challengeManager, $rp);
+    } catch (Throwable) {
+        header('HTTP/1.1 403 Unauthorized');
+        return;
+    }
+
+    // encode credentials to store to database
+    $codec = new Codecs\Credential();
+    $encodedCredential = $codec->encode($credential);
+
+
+    // save passkey
+    $User->save_passkey ($encodedCredential, $credential->getStorageId(), $data['keyId']);
+
+    // print result
+    header('HTTP/1.1 200 OK');
+    header('Content-type: application/json');
+    echo json_encode([
+            'success' => true,
+            'credentialId' => $credential->getStorageId()
+    ]);
+// } catch (exception $e) {
+//     header('HTTP/1.1 500 '.$e->getMessage());
+// }
+// catch (Throwable) {
+//     // Verification failed. Send an error to the user?
+//     header('HTTP/1.1 403 Unauthorized');
+//     return;
+// }
\ No newline at end of file
diff --git a/app/tools/user-menu/passkeys.php b/app/tools/user-menu/passkeys.php
index 240fd5cf..ed3c91b5 100644
--- a/app/tools/user-menu/passkeys.php
+++ b/app/tools/user-menu/passkeys.php
@@ -112,8 +112,7 @@ const startRegister = async (e) => {
     try {
     	// get and parse challenge
 		const challengeReq = await fetch('app/tools/user-menu/passkey_challenge.php')
-		const challengeB64 = await challengeReq.json()
-		const challenge    = atob(challengeB64) // base64-decode
+		const challenge    = await challengeReq.json()
 
 		// create
 	    const createOptions = {
@@ -127,16 +126,13 @@ const startRegister = async (e) => {
 	                id: Uint8Array.from("<?php print $User->user->id; ?>", c => c.charCodeAt(0)),
 	            },
 	            // This base64-decodes the response and translates it into the Webauthn-required format.
-	            challenge: Uint8Array.from(challenge, c => c.charCodeAt(0)),
+	            // challenge: Uint8Array.from(atob(challenge), c => c.charCodeAt(0)),
+	            challenge: Uint8Array.from(atob(challenge), c => c.charCodeAt(0)),
 	            pubKeyCredParams: [
 	                {
 	                    alg: -7, // ES256
 	                    type: "public-key",
-	                },
-				    {
-				    	alg: -257, // Value registered by this specification for "RS256"
-				    	type: "public-key",
-				    }
+	                }
 	            ]
 	        },
 	        attestation: 'direct',
@@ -145,12 +141,12 @@ const startRegister = async (e) => {
 	    // Call the WebAuthn browser API and get the response. This may throw, which you
 	    // should handle. Example: user cancels or never interacts with the device.
 	    const credential = await navigator.credentials.create(createOptions)
-        console.log(Array.from(new Uint8Array(credential.rawId)))
 
 	    // Format the credential to send to the server. This must match the format
 	    // handed by the ResponseParser class. The formatting code below can be used
 	    // without modification.
 	    const dataForResponseParser = {
+	        // rawId: Array.from(new Uint8Array(credential.rawId)),
 	        rawId: Array.from(new Uint8Array(credential.rawId)),
 	        keyId: credential.id,
 	        type: credential.type,
@@ -197,7 +193,7 @@ const startRegister = async (e) => {
     		});
         }
         else {
-            $('#loginCheckPasskeys').html("<div class='alert alert-danger'>Failed to register new passkey.</div>");
+            $('#loginCheckPasskeys').html("<div class='alert alert-danger'>Failed to register new passkey. <strong>Error : </strong>"+result.statusText+"</div>");
             console.log(result)
             $('div.loading').hide();
         }
diff --git a/functions/composer.json b/functions/composer.json
index 74c9d4e0..98208ceb 100644
--- a/functions/composer.json
+++ b/functions/composer.json
@@ -1,5 +1,6 @@
 {
     "require": {
-        "firehed/webauthn": "dev-main"
+        "firehed/webauthn": "dev-main",
+        "firehed/cbor": "^0.1.0"
     }
 }
diff --git a/functions/composer.lock b/functions/composer.lock
index ebb1323a..df24dd56 100644
--- a/functions/composer.lock
+++ b/functions/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "7bf730768732814406175c12775f3390",
+    "content-hash": "b0a7a5cc1994c275013de9975a5f2675",
     "packages": [
         {
             "name": "firehed/cbor",
@@ -59,12 +59,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/Firehed/webauthn-php.git",
-                "reference": "267d04a6d2926d9ab6d7630fb86a92410eb6b36c"
+                "reference": "e263a3553360d63131af707f3e563b151f4661b9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Firehed/webauthn-php/zipball/267d04a6d2926d9ab6d7630fb86a92410eb6b36c",
-                "reference": "267d04a6d2926d9ab6d7630fb86a92410eb6b36c",
+                "url": "https://api.github.com/repos/Firehed/webauthn-php/zipball/e263a3553360d63131af707f3e563b151f4661b9",
+                "reference": "e263a3553360d63131af707f3e563b151f4661b9",
                 "shasum": ""
             },
             "require": {
@@ -105,7 +105,7 @@
                 "issues": "https://github.com/Firehed/webauthn-php/issues",
                 "source": "https://github.com/Firehed/webauthn-php/tree/main"
             },
-            "time": "2023-11-16T23:07:44+00:00"
+            "time": "2023-12-10T19:00:08+00:00"
         }
     ],
     "packages-dev": [],
diff --git a/functions/vendor/autoload.php b/functions/vendor/autoload.php
index 29e50e81..1cca443d 100644
--- a/functions/vendor/autoload.php
+++ b/functions/vendor/autoload.php
@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
 
 require_once __DIR__ . '/composer/autoload_real.php';
 
-return ComposerAutoloaderInit7bf730768732814406175c12775f3390::getLoader();
+return ComposerAutoloaderInitb0a7a5cc1994c275013de9975a5f2675::getLoader();
diff --git a/functions/vendor/composer/autoload_real.php b/functions/vendor/composer/autoload_real.php
index 53cd7ae3..2aa2feed 100644
--- a/functions/vendor/composer/autoload_real.php
+++ b/functions/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInit7bf730768732814406175c12775f3390
+class ComposerAutoloaderInitb0a7a5cc1994c275013de9975a5f2675
 {
     private static $loader;
 
@@ -24,12 +24,12 @@ class ComposerAutoloaderInit7bf730768732814406175c12775f3390
 
         require __DIR__ . '/platform_check.php';
 
-        spl_autoload_register(array('ComposerAutoloaderInit7bf730768732814406175c12775f3390', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInitb0a7a5cc1994c275013de9975a5f2675', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
-        spl_autoload_unregister(array('ComposerAutoloaderInit7bf730768732814406175c12775f3390', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInitb0a7a5cc1994c275013de9975a5f2675', 'loadClassLoader'));
 
         require __DIR__ . '/autoload_static.php';
-        call_user_func(\Composer\Autoload\ComposerStaticInit7bf730768732814406175c12775f3390::getInitializer($loader));
+        call_user_func(\Composer\Autoload\ComposerStaticInitb0a7a5cc1994c275013de9975a5f2675::getInitializer($loader));
 
         $loader->register(true);
 
diff --git a/functions/vendor/composer/autoload_static.php b/functions/vendor/composer/autoload_static.php
index 2d75bd05..da8883f2 100644
--- a/functions/vendor/composer/autoload_static.php
+++ b/functions/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
 
 namespace Composer\Autoload;
 
-class ComposerStaticInit7bf730768732814406175c12775f3390
+class ComposerStaticInitb0a7a5cc1994c275013de9975a5f2675
 {
     public static $prefixLengthsPsr4 = array (
         'F' => 
@@ -32,9 +32,9 @@ class ComposerStaticInit7bf730768732814406175c12775f3390
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInit7bf730768732814406175c12775f3390::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInit7bf730768732814406175c12775f3390::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInit7bf730768732814406175c12775f3390::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInitb0a7a5cc1994c275013de9975a5f2675::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInitb0a7a5cc1994c275013de9975a5f2675::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInitb0a7a5cc1994c275013de9975a5f2675::$classMap;
 
         }, null, ClassLoader::class);
     }
diff --git a/functions/vendor/composer/installed.json b/functions/vendor/composer/installed.json
index 4c86530b..0c7c9064 100644
--- a/functions/vendor/composer/installed.json
+++ b/functions/vendor/composer/installed.json
@@ -57,12 +57,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/Firehed/webauthn-php.git",
-                "reference": "267d04a6d2926d9ab6d7630fb86a92410eb6b36c"
+                "reference": "e263a3553360d63131af707f3e563b151f4661b9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Firehed/webauthn-php/zipball/267d04a6d2926d9ab6d7630fb86a92410eb6b36c",
-                "reference": "267d04a6d2926d9ab6d7630fb86a92410eb6b36c",
+                "url": "https://api.github.com/repos/Firehed/webauthn-php/zipball/e263a3553360d63131af707f3e563b151f4661b9",
+                "reference": "e263a3553360d63131af707f3e563b151f4661b9",
                 "shasum": ""
             },
             "require": {
@@ -81,7 +81,7 @@
                 "phpunit/phpunit": "^9.3",
                 "squizlabs/php_codesniffer": "^3.5"
             },
-            "time": "2023-11-16T23:07:44+00:00",
+            "time": "2023-12-10T19:00:08+00:00",
             "default-branch": true,
             "type": "library",
             "installation-source": "source",
diff --git a/functions/vendor/composer/installed.php b/functions/vendor/composer/installed.php
index 384a408b..a4c65c37 100644
--- a/functions/vendor/composer/installed.php
+++ b/functions/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => '__root__',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => 'e75387138147905ffd3b12cafffdc10f5388d948',
+        'reference' => '7673d1b4aea9adf767af36a2cf418b7ad9091382',
         'type' => 'library',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -13,7 +13,7 @@
         '__root__' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => 'e75387138147905ffd3b12cafffdc10f5388d948',
+            'reference' => '7673d1b4aea9adf767af36a2cf418b7ad9091382',
             'type' => 'library',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
@@ -31,7 +31,7 @@
         'firehed/webauthn' => array(
             'pretty_version' => 'dev-main',
             'version' => 'dev-main',
-            'reference' => '267d04a6d2926d9ab6d7630fb86a92410eb6b36c',
+            'reference' => 'e263a3553360d63131af707f3e563b151f4661b9',
             'type' => 'library',
             'install_path' => __DIR__ . '/../firehed/webauthn',
             'aliases' => array(
diff --git a/functions/vendor/firehed/webauthn b/functions/vendor/firehed/webauthn
index 267d04a6..e263a355 160000
--- a/functions/vendor/firehed/webauthn
+++ b/functions/vendor/firehed/webauthn
@@ -1 +1 @@
-Subproject commit 267d04a6d2926d9ab6d7630fb86a92410eb6b36c
+Subproject commit e263a3553360d63131af707f3e563b151f4661b9
-- 
GitLab