diff --git a/static/js/webauthn.js b/static/js/webauthn.js index 9d9e502..d65a485 100644 --- a/static/js/webauthn.js +++ b/static/js/webauthn.js @@ -1,5 +1,5 @@ // Base64url encoding/decoding helpers for WebAuthn -function base64urlToBuffer(base64url) { +const base64urlToBuffer = (base64url) => { const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/"); const padded = base64 + "=".repeat((4 - (base64.length % 4)) % 4); const binary = atob(padded); @@ -8,43 +8,43 @@ function base64urlToBuffer(base64url) { bytes[i] = binary.charCodeAt(i); } return bytes.buffer; -} +}; -function bufferToBase64url(buffer) { +const bufferToBase64url = (buffer) => { const bytes = new Uint8Array(buffer); let binary = ""; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); -} +}; // Convert server challenge options to format navigator.credentials expects -function prepareCreationOptions(options) { +const prepareCreationOptions = (options) => { const publicKey = options.publicKey; publicKey.challenge = base64urlToBuffer(publicKey.challenge); publicKey.user.id = base64urlToBuffer(publicKey.user.id); if (publicKey.excludeCredentials) { - publicKey.excludeCredentials = publicKey.excludeCredentials.map(function (cred) { - return Object.assign({}, cred, { id: base64urlToBuffer(cred.id) }); - }); + publicKey.excludeCredentials = publicKey.excludeCredentials.map((cred) => + Object.assign({}, cred, { id: base64urlToBuffer(cred.id) }) + ); } return options; -} +}; -function prepareRequestOptions(options) { +const prepareRequestOptions = (options) => { const publicKey = options.publicKey; publicKey.challenge = base64urlToBuffer(publicKey.challenge); if (publicKey.allowCredentials) { - publicKey.allowCredentials = publicKey.allowCredentials.map(function (cred) { - return Object.assign({}, cred, { id: base64urlToBuffer(cred.id) }); - }); + publicKey.allowCredentials = publicKey.allowCredentials.map((cred) => + Object.assign({}, cred, { id: base64urlToBuffer(cred.id) }) + ); } return options; -} +}; // Serialize credential for sending back to server -function serializeRegistrationCredential(credential) { +const serializeRegistrationCredential = (credential) => { const response = credential.response; return { id: credential.id, @@ -55,9 +55,9 @@ function serializeRegistrationCredential(credential) { clientDataJSON: bufferToBase64url(response.clientDataJSON), }, }; -} +}; -function serializeAuthenticationCredential(credential) { +const serializeAuthenticationCredential = (credential) => { const response = credential.response; return { id: credential.id, @@ -70,10 +70,10 @@ function serializeAuthenticationCredential(credential) { userHandle: response.userHandle ? bufferToBase64url(response.userHandle) : null, }, }; -} +}; // Start passkey registration ceremony -async function startPasskeyRegistration(token, displayName, passkeyName) { +const startPasskeyRegistration = async (token, displayName, passkeyName) => { // 1. Get challenge from server const startResponse = await fetch("/api/v1/webauthn/register/start", { method: "POST", @@ -85,7 +85,7 @@ async function startPasskeyRegistration(token, displayName, passkeyName) { const status = startResponse.status; if (status === 401) throw new Error("Invalid registration token."); if (status === 410) throw new Error("Registration token has expired or already been used."); - throw new Error("Failed to start registration (HTTP " + status + ")."); + throw new Error(`Failed to start registration (HTTP ${status}).`); } const { challenge_id, options } = await startResponse.json(); @@ -106,22 +106,22 @@ async function startPasskeyRegistration(token, displayName, passkeyName) { }); if (!finishResponse.ok) { - throw new Error("Failed to complete registration (HTTP " + finishResponse.status + ")."); + throw new Error(`Failed to complete registration (HTTP ${finishResponse.status}).`); } return finishResponse.json(); -} +}; // Start passkey authentication ceremony -async function startPasskeyAuthentication(queryParams) { +const startPasskeyAuthentication = async (queryParams) => { // 1. Get challenge from server - const url = "/api/v1/webauthn/auth/start" + (queryParams || ""); + const url = `/api/v1/webauthn/auth/start${queryParams || ""}`; const startResponse = await fetch(url); if (!startResponse.ok) { const status = startResponse.status; if (status === 404) throw new Error("No passkeys registered. Please register first."); - throw new Error("Failed to start authentication (HTTP " + status + ")."); + throw new Error(`Failed to start authentication (HTTP ${status}).`); } const { challenge_id, options } = await startResponse.json(); @@ -141,14 +141,14 @@ async function startPasskeyAuthentication(queryParams) { }); if (!finishResponse.ok) { - throw new Error("Authentication failed (HTTP " + finishResponse.status + ")."); + throw new Error(`Authentication failed (HTTP ${finishResponse.status}).`); } return finishResponse.json(); -} +}; // Add a passkey to an existing authenticated account -async function addPasskey(name) { +const addPasskey = async (name) => { // 1. Get challenge from server const startResponse = await fetch("/api/v1/webauthn/passkey/start", { method: "POST", @@ -157,7 +157,7 @@ async function addPasskey(name) { }); if (!startResponse.ok) { - throw new Error("Failed to start passkey registration (HTTP " + startResponse.status + ")."); + throw new Error(`Failed to start passkey registration (HTTP ${startResponse.status}).`); } const { challenge_id, options } = await startResponse.json(); @@ -178,6 +178,6 @@ async function addPasskey(name) { }); if (!finishResponse.ok) { - throw new Error("Failed to complete passkey registration (HTTP " + finishResponse.status + ")."); + throw new Error(`Failed to complete passkey registration (HTTP ${finishResponse.status}).`); } -} +};