From 301c9493b14e58f4d03fe6027a418fe6b2332f59 Mon Sep 17 00:00:00 2001 From: Janis Steiner Date: Thu, 26 Dec 2024 13:12:24 +0100 Subject: [PATCH] finishing touches for passkey auth, oauth and more --- app-code/account/index.php | 44 +++++---------- app-code/api/account/update_passkey.php | 63 ++++++--------------- app-code/api/auth/check_auth_key.php | 55 ++++++++++++++++++ app-code/api/login/check_passkey.php | 74 ++++++++----------------- app-code/api/login/redirect.php | 32 ++++++++--- app-code/index.php | 4 ++ app-code/install/create_db.php | 22 +++++++- app-code/login/passkey.php | 61 ++++++++------------ app-code/plugins/auth.php | 50 +++++++++++++++++ 9 files changed, 232 insertions(+), 173 deletions(-) create mode 100644 app-code/api/auth/check_auth_key.php create mode 100644 app-code/plugins/auth.php diff --git a/app-code/account/index.php b/app-code/account/index.php index f063242..148f248 100644 --- a/app-code/account/index.php +++ b/app-code/account/index.php @@ -280,17 +280,6 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) { }); }); - // Function to show error modal - function showErrorModal(message) { - document.getElementById('errorModalMessage').textContent = message; - const errorModal = new bootstrap.Modal(document.getElementById('errorModal')); - errorModal.show(); - } - function showSuccessModal(message) { - document.getElementById('successModalMessage').textContent = message; - const errorModal = new bootstrap.Modal(document.getElementById('successModal')); - errorModal.show(); - } //////////////////////////////////////////// @@ -328,6 +317,18 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) { } }); }); + + // Function to show error modal + function showErrorModal(message) { + document.getElementById('errorModalMessage').textContent = message; + const errorModal = new bootstrap.Modal(document.getElementById('errorModal')); + errorModal.show(); + } + function showSuccessModal(message) { + document.getElementById('successModalMessage').textContent = message; + const errorModal = new bootstrap.Modal(document.getElementById('successModal')); + errorModal.show(); + } //webauthn js async function createRegistration() { @@ -374,34 +375,17 @@ if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) { // prompt server response if (authenticatorAttestationServerResponse.success) { reloadServerPreview(); - window.alert(authenticatorAttestationServerResponse.msg || 'registration success'); + showSuccessModal(authenticatorAttestationServerResponse.msg || 'Registrated passkey successfully'); } else { throw new Error(authenticatorAttestationServerResponse.msg); } } catch (err) { reloadServerPreview(); - window.alert(err.message || 'unknown error occured'); + showErrorModal(err.message || 'unknown error occured'); } } - - - function queryFidoMetaDataService() { - window.fetch('/api/account/update_passkey.php?fn=queryFidoMetaDataService' + getGetParams(), {method:'GET',cache:'no-cache'}).then(function(response) { - return response.json(); - - }).then(function(json) { - if (json.success) { - window.alert(json.msg); - } else { - throw new Error(json.msg); - } - }).catch(function(err) { - window.alert(err.message || 'unknown error occured'); - }); - } - /** * convert RFC 1342-like base64 strings to array buffer * @param {mixed} obj diff --git a/app-code/api/account/update_passkey.php b/app-code/api/account/update_passkey.php index 08dfcdd..bc3c6f0 100644 --- a/app-code/api/account/update_passkey.php +++ b/app-code/api/account/update_passkey.php @@ -46,36 +46,22 @@ try { if ($fn !== 'getStoredDataHtml') { // Formats - $formats = []; - //if (filter_input(INPUT_GET, 'fmt_android-key')) { - $formats[] = 'android-key'; - //} - ///if (filter_input(INPUT_GET, 'fmt_android-safetynet')) { - $formats[] = 'android-safetynet'; - //} - //if (filter_input(INPUT_GET, 'fmt_apple')) { - $formats[] = 'apple'; - //} - //if (filter_input(INPUT_GET, 'fmt_fido-u2f')) { - $formats[] = 'fido-u2f'; - //} - //if (filter_input(INPUT_GET, 'fmt_none')) { - $formats[] = 'none'; - //} - //if (filter_input(INPUT_GET, 'fmt_packed')) { - $formats[] = 'packed'; - //} - //if (filter_input(INPUT_GET, 'fmt_tpm')) { - $formats[] = 'tpm'; - //} + $formats = []; + $formats[] = 'android-key'; + $formats[] = 'android-safetynet'; + $formats[] = 'apple'; + $formats[] = 'fido-u2f'; + $formats[] = 'none'; + $formats[] = 'packed'; + $formats[] = 'tpm'; - $rpId=$_SERVER['SERVER_NAME']; - - $typeUsb = true; - $typeNfc = true; - $typeBle = true; - $typeInt = true; - $typeHyb = true; + $rpId=$_SERVER['SERVER_NAME']; + + $typeUsb = true; + $typeNfc = true; + $typeBle = true; + $typeInt = true; + $typeHyb = true; // cross-platform: true, if type internal is not allowed // false, if only internal is allowed @@ -94,28 +80,14 @@ try { $WebAuthn = new lbuchs\WebAuthn\WebAuthn('WebAuthn Library', $rpId, $formats); // add root certificates to validate new registrations - //if (filter_input(INPUT_GET, 'solo')) { $WebAuthn->addRootCertificates('rootCertificates/solo.pem'); - //} - //if (filter_input(INPUT_GET, 'apple')) { $WebAuthn->addRootCertificates('rootCertificates/apple.pem'); - //} - //if (filter_input(INPUT_GET, 'yubico')) { $WebAuthn->addRootCertificates('rootCertificates/yubico.pem'); - //} - //if (filter_input(INPUT_GET, 'hypersecu')) { $WebAuthn->addRootCertificates('rootCertificates/hypersecu.pem'); - //} - //if (filter_input(INPUT_GET, 'google')) { $WebAuthn->addRootCertificates('rootCertificates/globalSign.pem'); $WebAuthn->addRootCertificates('rootCertificates/googleHardware.pem'); - //} - //if (filter_input(INPUT_GET, 'microsoft')) { $WebAuthn->addRootCertificates('rootCertificates/microsoftTpmCollection.pem'); - //} - //if (filter_input(INPUT_GET, 'mds')) { $WebAuthn->addRootCertificates('rootCertificates/mds'); - //} } @@ -176,9 +148,7 @@ try { $data->userDisplayName = $userDisplayName; // Store registration data in the database - $stmt = $conn->prepare("UPDATE users set credential_id = ?, public_key = ?, counter = ?, auth_method_enabled_passkey = 1, auth_method_required_passkey = 1 WHERE username = ?"); - //$stmt = $conn->prepare("INSERT INTO users (user_hex_id, credential_id, public_key, counter) VALUES (?, ?, ?, ?)"); - //var_dump($data); + $stmt = $conn->prepare("UPDATE users set credential_id = ?, public_key = ?, counter = ?, auth_method_enabled_passkey = 1, auth_method_required_passkey = 1 WHERE username = ?"); $stmt->execute([ $data->credentialId, $data->credentialPublicKey, $data->signatureCounter,$userName]); $msg = 'registration success.'; @@ -198,3 +168,4 @@ try { print(json_encode($return)); } ?> + diff --git a/app-code/api/auth/check_auth_key.php b/app-code/api/auth/check_auth_key.php new file mode 100644 index 0000000..1095af5 --- /dev/null +++ b/app-code/api/auth/check_auth_key.php @@ -0,0 +1,55 @@ +'success', + 'msg'=>'user authenticated', + 'username'=>$username, + 'email'=>$email, + 'telegram_id'=>$telegram, + 'id'=>$user_id + ]; + + //remove auth key + $sql="DELETE FROM auth_tokens WHERE auth_token = ?;"; + $stmt = mysqli_prepare($conn, $sql); + mysqli_stmt_bind_param($stmt, 's', $auth_key); + mysqli_stmt_execute($stmt); + echo(json_encode($data)); +}else{ + $data=[ + 'status' => 'failure', + 'msg'=>'invalid auth key', + 'auth_key'=>$auth_key + ]; + echo(json_encode($data)); +} + +?> diff --git a/app-code/api/login/check_passkey.php b/app-code/api/login/check_passkey.php index 8d0284c..1f286f5 100644 --- a/app-code/api/login/check_passkey.php +++ b/app-code/api/login/check_passkey.php @@ -32,36 +32,22 @@ try { if ($fn !== 'getStoredDataHtml') { // Formats - $formats = []; - //if (filter_input(INPUT_GET, 'fmt_android-key')) { - $formats[] = 'android-key'; - //} - ///if (filter_input(INPUT_GET, 'fmt_android-safetynet')) { - $formats[] = 'android-safetynet'; - //} - //if (filter_input(INPUT_GET, 'fmt_apple')) { - $formats[] = 'apple'; - //} - //if (filter_input(INPUT_GET, 'fmt_fido-u2f')) { - $formats[] = 'fido-u2f'; - //} - //if (filter_input(INPUT_GET, 'fmt_none')) { - $formats[] = 'none'; - //} - //if (filter_input(INPUT_GET, 'fmt_packed')) { - $formats[] = 'packed'; - //} - //if (filter_input(INPUT_GET, 'fmt_tpm')) { - $formats[] = 'tpm'; - //} + $formats = []; + $formats[] = 'android-key'; + $formats[] = 'android-safetynet'; + $formats[] = 'apple'; + $formats[] = 'fido-u2f'; + $formats[] = 'none'; + $formats[] = 'packed'; + $formats[] = 'tpm'; - $rpId=$_SERVER['SERVER_NAME']; - - $typeUsb = true; - $typeNfc = true; - $typeBle = true; - $typeInt = true; - $typeHyb = true; + $rpId=$_SERVER['SERVER_NAME']; + + $typeUsb = true; + $typeNfc = true; + $typeBle = true; + $typeInt = true; + $typeHyb = true; // cross-platform: true, if type internal is not allowed // false, if only internal is allowed @@ -80,28 +66,14 @@ try { $WebAuthn = new lbuchs\WebAuthn\WebAuthn('WebAuthn Library', $rpId, $formats); // add root certificates to validate new registrations - //if (filter_input(INPUT_GET, 'solo')) { - $WebAuthn->addRootCertificates('rootCertificates/solo.pem'); - //} - //if (filter_input(INPUT_GET, 'apple')) { - $WebAuthn->addRootCertificates('rootCertificates/apple.pem'); - //} - //if (filter_input(INPUT_GET, 'yubico')) { - $WebAuthn->addRootCertificates('rootCertificates/yubico.pem'); - //} - //if (filter_input(INPUT_GET, 'hypersecu')) { - $WebAuthn->addRootCertificates('rootCertificates/hypersecu.pem'); - //} - //if (filter_input(INPUT_GET, 'google')) { - $WebAuthn->addRootCertificates('rootCertificates/globalSign.pem'); - $WebAuthn->addRootCertificates('rootCertificates/googleHardware.pem'); - //} - //if (filter_input(INPUT_GET, 'microsoft')) { - $WebAuthn->addRootCertificates('rootCertificates/microsoftTpmCollection.pem'); - //} - //if (filter_input(INPUT_GET, 'mds')) { - $WebAuthn->addRootCertificates('rootCertificates/mds'); - //} + $WebAuthn->addRootCertificates('rootCertificates/solo.pem'); + $WebAuthn->addRootCertificates('rootCertificates/apple.pem'); + $WebAuthn->addRootCertificates('rootCertificates/yubico.pem'); + $WebAuthn->addRootCertificates('rootCertificates/hypersecu.pem'); + $WebAuthn->addRootCertificates('rootCertificates/globalSign.pem'); + $WebAuthn->addRootCertificates('rootCertificates/googleHardware.pem'); + $WebAuthn->addRootCertificates('rootCertificates/microsoftTpmCollection.pem'); + $WebAuthn->addRootCertificates('rootCertificates/mds'); } diff --git a/app-code/api/login/redirect.php b/app-code/api/login/redirect.php index 550a1a9..4117fff 100644 --- a/app-code/api/login/redirect.php +++ b/app-code/api/login/redirect.php @@ -23,20 +23,35 @@ else if($_SESSION["needs_auth"]===false && $_SESSION["mfa_required"]==1 && $_SES //check for mfa } -else if($_SESSION["needs_auth"]===false && $_SESSION["passkey_required"]==1 && $_SESSION["passkey_authenticated"]==0){ +/*else if($_SESSION["needs_auth"]===false && $_SESSION["passkey_required"]==1 && $_SESSION["passkey_authenticated"]==0){ //check for passkey $data=[ 'message' => 'auth_passkey', 'redirect' => '/login/passkey.php' ]; echo(json_encode($data)); -}else if ($_SESSION["needs_auth"]===false && $_SESSION["mfa_authenticated"]==1 && $_SESSION["pw_authenticated"]==1 && $_SESSION["passkey_authenticated"]){ +}*/else if ($_SESSION["needs_auth"]===false && $_SESSION["mfa_authenticated"]==1 && $_SESSION["pw_authenticated"]==1){ //fully authenticated $_SESSION["logged_in"]=true; - $data=[ - 'message' => 'done', - 'redirect' => $send_to - ]; + //create auth token which other services can then use to check if user logged in + $user_id=$_SESSION["id"]; + $auth_token=bin2hex(random_bytes(128)); + $sql="INSERT INTO auth_tokens (auth_token,user_id) VALUES(?,?);"; + $stmt = mysqli_prepare($conn, $sql); + mysqli_stmt_bind_param($stmt, 'si', $auth_token,$user_id); + mysqli_stmt_execute($stmt); + mysqli_stmt_close($stmt); + if(!empty($send_to)){ + $data=[ + 'message' => 'done', + 'redirect' => $send_to."?auth=$auth_token" + ]; + }else{ + $data=[ + 'message' => 'done', + 'redirect' => '' + ]; + } echo(json_encode($data)); } else{ @@ -45,7 +60,7 @@ else{ $username=$_SESSION["username"]; $_SESSION["needs_auth"]=false; $_SESSION["logged_in"]=false; - $sql="SELECT auth_method_required_pw, auth_method_required_2fa, auth_method_required_passkey FROM users WHERE username = ?"; + $sql="SELECT auth_method_required_pw, auth_method_required_2fa, auth_method_required_passkey, id FROM users WHERE username = ?"; $stmt = mysqli_prepare($conn, $sql); mysqli_stmt_bind_param($stmt, 's', $username); mysqli_stmt_execute($stmt); @@ -54,7 +69,7 @@ else{ $mfa=0; $passkey=0; if(mysqli_stmt_num_rows($stmt) == 1){ - mysqli_stmt_bind_result($stmt, $pw,$mfa,$passkey); + mysqli_stmt_bind_result($stmt, $pw,$mfa,$passkey,$user_id); mysqli_stmt_fetch($stmt); $_SESSION["pw_required"] = $pw; $_SESSION["pw_authenticated"] = ($pw == 0) ? 1 : 0; // If $pw is 0, set pw_authenticated to 1 @@ -62,6 +77,7 @@ else{ $_SESSION["mfa_authenticated"] = ($mfa == 0) ? 1 : 0; $_SESSION["passkey_required"] = $passkey; $_SESSION["passkey_authenticated"] = ($passkey == 0) ? 1 : 0; + $_SESSION["id"]=$user_id; $data=[ 'message' => 'prepared_start_auth', 'redirect' => '/login/' diff --git a/app-code/index.php b/app-code/index.php index 85278fb..887d961 100644 --- a/app-code/index.php +++ b/app-code/index.php @@ -10,6 +10,10 @@ include "assets/components.php"; session_start(); $_SESSION["end_url"]=$_GET["send_to"]; + if (isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] === true) { + header("LOCATION:/login/"); + exit(); + } ?> diff --git a/app-code/install/create_db.php b/app-code/install/create_db.php index 12c20eb..f2ddfe4 100644 --- a/app-code/install/create_db.php +++ b/app-code/install/create_db.php @@ -61,7 +61,7 @@ id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255) NOT NULL UNIQUE, public_key TEXT DEFAULT '', - credential_id VARBINARY(64), + credential_id VARBINARY(255), counter INT DEFAULT 0, 2fa VARCHAR(255), email VARCHAR(255), @@ -93,6 +93,26 @@ '; } + + + $sql="CREATE TABLE IF NOT EXISTS auth_tokens ( + id INT AUTO_INCREMENT PRIMARY KEY, + auth_token VARCHAR(256), + user_id INT + );"; + + + if ($conn->query($sql) === TRUE) { + echo '
'; + } else { + $success=0; + echo '
'; + } + if($success!==1){ diff --git a/app-code/login/passkey.php b/app-code/login/passkey.php index f2c9cd0..53addcc 100644 --- a/app-code/login/passkey.php +++ b/app-code/login/passkey.php @@ -31,27 +31,32 @@ -