summaryrefslogtreecommitdiff
path: root/internal/ui/static/js/webauthn.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/ui/static/js/webauthn.js196
1 files changed, 0 insertions, 196 deletions
diff --git a/internal/ui/static/js/webauthn.js b/internal/ui/static/js/webauthn.js
deleted file mode 100644
index 465aa49e..00000000
--- a/internal/ui/static/js/webauthn.js
+++ /dev/null
@@ -1,196 +0,0 @@
-function isWebAuthnSupported() {
- return window.PublicKeyCredential;
-}
-
-async function isConditionalLoginSupported() {
- return isWebAuthnSupported() &&
- window.PublicKeyCredential.isConditionalMediationAvailable &&
- window.PublicKeyCredential.isConditionalMediationAvailable();
-}
-
-// URLBase64 to ArrayBuffer
-function bufferDecode(value) {
- return Uint8Array.from(atob(value.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0));
-}
-
-// ArrayBuffer to URLBase64
-function bufferEncode(value) {
- return btoa(String.fromCharCode.apply(null, new Uint8Array(value)))
- .replace(/\+/g, "-")
- .replace(/\//g, "_")
- .replace(/=/g, "");
-}
-
-function getCsrfToken() {
- let element = document.querySelector("body[data-csrf-token]");
- if (element !== null) {
- return element.dataset.csrfToken;
- }
- return "";
-}
-
-async function post(urlKey, username, data) {
- var url = document.body.dataset[urlKey];
- if (username) {
- url += "?username=" + username;
- }
- return fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- "X-Csrf-Token": getCsrfToken()
- },
- body: JSON.stringify(data),
- });
-}
-
-async function get(urlKey, username) {
- var url = document.body.dataset[urlKey];
- if (username) {
- url += "?username=" + username;
- }
- return fetch(url);
-}
-
-function showError(error) {
- console.log("webauthn error: " + error);
- let alert = document.getElementById("webauthn-error");
- if (alert) {
- alert.classList.remove("hidden");
- }
-}
-
-async function register() {
- let beginRegisterURL = "webauthnRegisterBeginUrl";
- let r = await get(beginRegisterURL);
- let credOptions = await r.json();
- credOptions.publicKey.challenge = bufferDecode(credOptions.publicKey.challenge);
- credOptions.publicKey.user.id = bufferDecode(credOptions.publicKey.user.id);
- if(Object.hasOwn(credOptions.publicKey, 'excludeCredentials')) {
- credOptions.publicKey.excludeCredentials.forEach((credential) => credential.id = bufferDecode(credential.id));
- }
- let attestation = await navigator.credentials.create(credOptions);
- let cred = {
- id: attestation.id,
- rawId: bufferEncode(attestation.rawId),
- type: attestation.type,
- response: {
- attestationObject: bufferEncode(attestation.response.attestationObject),
- clientDataJSON: bufferEncode(attestation.response.clientDataJSON),
- },
- };
- let finishRegisterURL = "webauthnRegisterFinishUrl";
- let response = await post(finishRegisterURL, null, cred);
- if (!response.ok) {
- throw new Error("Login failed with HTTP status " + response.status);
- }
- console.log("registration successful");
-
- let jsonData = await response.json();
- let redirect = jsonData.redirect;
- window.location.href = redirect;
-}
-
-async function login(username, conditional) {
- let beginLoginURL = "webauthnLoginBeginUrl";
- let r = await get(beginLoginURL, username);
- let credOptions = await r.json();
- credOptions.publicKey.challenge = bufferDecode(credOptions.publicKey.challenge);
- if(Object.hasOwn(credOptions.publicKey, 'allowCredentials')) {
- credOptions.publicKey.allowCredentials.forEach((credential) => credential.id = bufferDecode(credential.id));
- }
- if (conditional) {
- credOptions.signal = abortController.signal;
- credOptions.mediation = "conditional";
- }
-
- var assertion;
- try {
- assertion = await navigator.credentials.get(credOptions);
- }
- catch (err) {
- // swallow aborted conditional logins
- if (err instanceof DOMException && err.name == "AbortError") {
- return;
- }
- throw err;
- }
-
- if (!assertion) {
- return;
- }
-
- let assertionResponse = {
- id: assertion.id,
- rawId: bufferEncode(assertion.rawId),
- type: assertion.type,
- response: {
- authenticatorData: bufferEncode(assertion.response.authenticatorData),
- clientDataJSON: bufferEncode(assertion.response.clientDataJSON),
- signature: bufferEncode(assertion.response.signature),
- userHandle: bufferEncode(assertion.response.userHandle),
- },
- };
-
- let finishLoginURL = "webauthnLoginFinishUrl";
- let response = await post(finishLoginURL, username, assertionResponse);
- if (!response.ok) {
- throw new Error("Login failed with HTTP status " + response.status);
- }
- window.location.reload();
-}
-
-async function conditionalLogin() {
- if (await isConditionalLoginSupported()) {
- login("", true);
- }
-}
-
-async function removeCreds(event) {
- event.preventDefault();
- let removeCredsURL = "webauthnDeleteAllUrl";
- await post(removeCredsURL, null, {});
- window.location.reload();
-}
-
-let abortController = new AbortController();
-document.addEventListener("DOMContentLoaded", function () {
- if (!isWebAuthnSupported()) {
- return;
- }
-
- let registerButton = document.getElementById("webauthn-register");
- if (registerButton != null) {
- registerButton.disabled = false;
- registerButton.addEventListener("click", (e) => {
- e.preventDefault();
- register().catch((err) => showError(err));
- });
- }
-
- let removeCredsButton = document.getElementById("webauthn-delete");
- if (removeCredsButton != null) {
- removeCredsButton.addEventListener("click", removeCreds);
- }
-
- let loginButton = document.getElementById("webauthn-login");
- if (loginButton != null) {
- loginButton.disabled = false;
- let usernameField = document.getElementById("form-username");
- if (usernameField != null) {
- usernameField.autocomplete += " webauthn";
- }
- let passwordField = document.getElementById("form-password");
- if (passwordField != null) {
- passwordField.autocomplete += " webauthn";
- }
-
- loginButton.addEventListener("click", (e) => {
- e.preventDefault();
- abortController.abort();
- login(usernameField.value).catch(err => showError(err));
- });
-
- conditionalLogin().catch(err => showError(err));
- }
-});