about summary refs log tree commit diff
path: root/templates/javascript/dist/indieauth.js
diff options
context:
space:
mode:
Diffstat (limited to 'templates/javascript/dist/indieauth.js')
-rw-r--r--templates/javascript/dist/indieauth.js118
1 files changed, 118 insertions, 0 deletions
diff --git a/templates/javascript/dist/indieauth.js b/templates/javascript/dist/indieauth.js
new file mode 100644
index 0000000..297b4b5
--- /dev/null
+++ b/templates/javascript/dist/indieauth.js
@@ -0,0 +1,118 @@
+"use strict";
+const WEBAUTHN_TIMEOUT = 60 * 1000;
+async function webauthn_create_credential() {
+    const response = await fetch("/.kittybox/webauthn/pre_register");
+    const { challenge, rp, user } = await response.json();
+    return await navigator.credentials.create({
+        publicKey: {
+            challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
+            rp: rp,
+            user: {
+                id: Uint8Array.from(user.cred_id, (c) => c.charCodeAt(0)),
+                name: user.name,
+                displayName: user.displayName
+            },
+            pubKeyCredParams: [{ alg: -7, type: "public-key" }],
+            authenticatorSelection: {},
+            timeout: WEBAUTHN_TIMEOUT,
+            attestation: "none"
+        }
+    });
+}
+async function webauthn_authenticate() {
+    const response = await fetch("/.kittybox/webauthn/pre_auth");
+    const { challenge, credentials } = await response.json();
+    try {
+        return await navigator.credentials.get({
+            publicKey: {
+                challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
+                allowCredentials: credentials.map(cred => ({
+                    id: Uint8Array.from(cred.id, c => c.charCodeAt(0)),
+                    type: cred.type
+                })),
+                timeout: WEBAUTHN_TIMEOUT
+            }
+        });
+    }
+    catch (e) {
+        console.error("WebAuthn authentication failed:", e);
+        alert("Using your authenticator failed. (Check the DevTools for details)");
+        throw e;
+    }
+}
+async function submit_handler(e) {
+    e.preventDefault();
+    if (e.target != null && e.target instanceof HTMLFormElement) {
+        const form = e.target;
+        let scopes;
+        if (form.elements.namedItem("scope") === undefined) {
+            scopes = [];
+        }
+        else if (form.elements.namedItem("scope") instanceof Node) {
+            scopes = [form.elements.namedItem("scope")]
+                .filter((e) => e.checked)
+                .map((e) => e.value);
+        }
+        else {
+            scopes = Array.from(form.elements.namedItem("scope"))
+                .filter((e) => e.checked)
+                .map((e) => e.value);
+        }
+        const authorization_request = {
+            response_type: form.elements.namedItem("response_type").value,
+            client_id: form.elements.namedItem("client_id").value,
+            redirect_uri: form.elements.namedItem("redirect_uri").value,
+            state: form.elements.namedItem("state").value,
+            code_challenge: form.elements.namedItem("code_challenge").value,
+            code_challenge_method: form.elements.namedItem("code_challenge_method").value,
+            // I would love to leave that as a list, but such is the form of
+            // IndieAuth.  application/x-www-form-urlencoded doesn't have
+            // lists, so scopes are space-separated instead. It is annoying.
+            scope: scopes.length > 0 ? scopes.join(" ") : undefined,
+        };
+        let credential = null;
+        switch (form.elements.namedItem("auth_method").value) {
+            case "password":
+                credential = form.elements.namedItem("user_password").value;
+                if (credential.length == 0) {
+                    alert("Please enter a password.");
+                    return;
+                }
+                break;
+            case "webauthn":
+                // credential = await webauthn_authenticate();
+                alert("WebAuthn isn't implemented yet!");
+                return;
+                break;
+            default:
+                alert("Please choose an authentication method.");
+                return;
+        }
+        console.log("Authorization request:", authorization_request);
+        console.log("Authentication method:", credential);
+        const body = JSON.stringify({
+            request: authorization_request,
+            authorization_method: credential
+        });
+        console.log(body);
+        const response = await fetch(form.action, {
+            method: form.method,
+            body: body,
+            headers: {
+                "Content-Type": "application/json"
+            }
+        });
+        if (response.ok) {
+            let location = response.headers.get("Location");
+            if (location != null) {
+                window.location.href = location;
+            }
+            else {
+                throw "Error: didn't return a location";
+            }
+        }
+    }
+    else {
+        return;
+    }
+}