diff --git a/internal/api/ui/login/static/resources/scripts/webauthn.js b/internal/api/ui/login/static/resources/scripts/webauthn.js index e8d9c54f41..9fafef8030 100644 --- a/internal/api/ui/login/static/resources/scripts/webauthn.js +++ b/internal/api/ui/login/static/resources/scripts/webauthn.js @@ -15,7 +15,17 @@ function checkWebauthnSupported(button, func) { function webauthnError(error) { let err = document.getElementById("wa-error"); - err.getElementsByClassName("cause")[0].innerText = error.message; + let causeElement = err.getElementsByClassName("cause")[0]; + + if (error.message) { + causeElement.innerText = error.message; + } else if (error.value) { + causeElement.innerText = error.value; + } else { + console.error("Unknown error:", error); + causeElement.innerText = "An unknown error occurred."; + } + err.classList.remove("hidden"); } diff --git a/internal/api/ui/login/static/resources/scripts/webauthn_login.js b/internal/api/ui/login/static/resources/scripts/webauthn_login.js index 4265d76e62..3bf6c4c754 100644 --- a/internal/api/ui/login/static/resources/scripts/webauthn_login.js +++ b/internal/api/ui/login/static/resources/scripts/webauthn_login.js @@ -3,29 +3,36 @@ document.addEventListener( checkWebauthnSupported("btn-login", login) ); -function login() { +async function login() { document.getElementById("wa-error").classList.add("hidden"); - let makeAssertionOptions = JSON.parse( - atob(document.getElementsByName("credentialAssertionData")[0].value) - ); - makeAssertionOptions.publicKey.challenge = bufferDecode( - makeAssertionOptions.publicKey.challenge, - "publicKey.challenge" - ); - makeAssertionOptions.publicKey.allowCredentials.forEach(function (listItem) { - listItem.id = bufferDecode(listItem.id, "publicKey.allowCredentials.id"); - }); - navigator.credentials - .get({ - publicKey: makeAssertionOptions.publicKey, - }) - .then(function (credential) { - verifyAssertion(credential); - }) - .catch(function (err) { - webauthnError(err); + let makeAssertionOptions; + try { + makeAssertionOptions = JSON.parse(atob(document.getElementsByName("credentialAssertionData")[0].value)); + } catch (e) { + webauthnError({ message: "Failed to parse credential assertion data." }); + return; + } + + try { + makeAssertionOptions.publicKey.challenge = bufferDecode(makeAssertionOptions.publicKey.challenge, "publicKey.challenge"); + makeAssertionOptions.publicKey.allowCredentials.forEach(function (listItem) { + listItem.id = bufferDecode(listItem.id, "publicKey.allowCredentials.id"); }); + } catch (e) { + webauthnError({ message: "Failed to decode buffer data." }); + return; + } + + try { + const credential = await navigator.credentials.get({ + publicKey: makeAssertionOptions.publicKey, + }); + + verifyAssertion(credential); + } catch (err) { + webauthnError(err); + } } function verifyAssertion(assertedCredential) { @@ -49,6 +56,6 @@ function verifyAssertion(assertedCredential) { }, }); - document.getElementsByName("credentialData")[0].value = btoa(data); + document.getElementsByName("credentialData")[0].value = window.btoa(data); document.getElementsByTagName("form")[0].submit(); } diff --git a/internal/api/ui/login/static/resources/scripts/webauthn_register.js b/internal/api/ui/login/static/resources/scripts/webauthn_register.js index 7ce875905b..dd33f18933 100644 --- a/internal/api/ui/login/static/resources/scripts/webauthn_register.js +++ b/internal/api/ui/login/static/resources/scripts/webauthn_register.js @@ -3,40 +3,41 @@ document.addEventListener( checkWebauthnSupported("btn-register", registerCredential) ); -function registerCredential() { +async function registerCredential() { document.getElementById("wa-error").classList.add("hidden"); - let opt = JSON.parse( - atob(document.getElementsByName("credentialCreationData")[0].value) - ); - opt.publicKey.challenge = bufferDecode( - opt.publicKey.challenge, - "publicKey.challenge" - ); - opt.publicKey.user.id = bufferDecode( - opt.publicKey.user.id, - "publicKey.user.id" - ); - if (opt.publicKey.excludeCredentials) { - for (let i = 0; i < opt.publicKey.excludeCredentials.length; i++) { - if (opt.publicKey.excludeCredentials[i].id !== null) { - opt.publicKey.excludeCredentials[i].id = bufferDecode( - opt.publicKey.excludeCredentials[i].id, - "publicKey.excludeCredentials" - ); + let opt; + try { + opt = JSON.parse(atob(document.getElementsByName("credentialCreationData")[0].value)); + } catch (e) { + webauthnError({ message: "Failed to parse credential creation data." }); + return; + } + + try { + opt.publicKey.challenge = bufferDecode(opt.publicKey.challenge, "publicKey.challenge"); + opt.publicKey.user.id = bufferDecode(opt.publicKey.user.id, "publicKey.user.id"); + if (opt.publicKey.excludeCredentials) { + for (let i = 0; i < opt.publicKey.excludeCredentials.length; i++) { + if (opt.publicKey.excludeCredentials[i].id !== null) { + opt.publicKey.excludeCredentials[i].id = bufferDecode(opt.publicKey.excludeCredentials[i].id, "publicKey.excludeCredentials"); + } } } + } catch (e) { + webauthnError({ message: "Failed to decode buffer data." }); + return; } - navigator.credentials - .create({ + + try { + const credential = await navigator.credentials.create({ publicKey: opt.publicKey, - }) - .then(function (credential) { - createCredential(credential); - }) - .catch(function (err) { - webauthnError(err); }); + + createCredential(credential); + } catch (err) { + webauthnError(err); + } } function createCredential(newCredential) { @@ -56,6 +57,6 @@ function createCredential(newCredential) { }, }); - document.getElementsByName("credentialData")[0].value = btoa(data); + document.getElementsByName("credentialData")[0].value = window.btoa(data); document.getElementsByTagName("form")[0].submit(); }