document.getElementById("registerButton").addEventListener("click", register); document.getElementById("loginButton").addEventListener("click", login); function showMessage(message, isError = false) { console.log("got message", message); const messageElement = document.getElementById("message"); messageElement.textContent = message; messageElement.style.color = isError ? "red" : "green"; } async function register() { // Retrieve the username from the input field const username = document.getElementById("username").value; try { // Get registration options from your server. Here, we also receive the challenge. const response = await fetch("/webauthn/passkey/registerBegin", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: username }), }); // Check if the registration options are ok. if (!response.ok) { const msg = await response.json(); throw new Error( "User already exists or failed to get registration options from server: " + msg, ); } // Convert the registration options to JSON. const options = await response.json(); console.log("registration start", options); // This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello). // A new attestation is created. This also means a new public-private-key pair is created. const attestationResponse = await SimpleWebAuthnBrowser.startRegistration( options.publicKey, ); console.log("Attempting to complete registration", attestationResponse); // Send attestationResponse back to server for verification and storage. const verificationResponse = await fetch( "/webauthn/passkey/registerFinish", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json", }, body: JSON.stringify(attestationResponse), }, ); console.log("Registration finish"); const msg = await verificationResponse.json(); console.log("register full response", verificationResponse); console.log("register body", msg); if (verificationResponse.ok) { showMessage(msg, false); } else { showMessage(msg, true); } } catch (error) { console.log("Received error", error); showMessage("Error: " + error.message, true); } } async function login() { // Retrieve the username from the input field const username = document.getElementById("username").value; try { // Get login options from your server. Here, we also receive the challenge. const response = await fetch("/webauthn/passkey/loginBegin", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: username }), }); // Check if the login options are ok. if (!response.ok) { const msg = await response.json(); throw new Error("Failed to get login options from server: " + msg); } // Convert the login options to JSON. const options = await response.json(); // This triggers the browser to display the passkey / WebAuthn modal (e.g. Face ID, Touch ID, Windows Hello). // A new assertionResponse is created. This also means that the challenge has been signed. const assertionResponse = await SimpleWebAuthnBrowser.startAuthentication( options.publicKey, ); // Send assertionResponse back to server for verification. const verificationResponse = await fetch("/webauthn/passkey/loginFinish", { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json", }, body: JSON.stringify(assertionResponse), }); console.log("login done"); const msg = await verificationResponse.json(); console.log("login-response", verificationResponse); console.log("login-body", msg); if (verificationResponse.ok) { showMessage(msg, false); } else { showMessage(msg, true); } } catch (error) { console.log("received error", error); showMessage("Error: " + error.message, true); } }