diff options
| author | tv <tv@krebsco.de> | 2026-11-07 22:35:22 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-07 22:35:22 +0100 |
| commit | 56a3dca1874fba17c3d174be451af9478b3bfb9d (patch) | |
| tree | 819e3a1d4902c6847b429dd69269ef475d067a45 /src/api/dashboard/login.html | |
| parent | 7323e8ed8598cda9784493aa3334d947120b53d8 (diff) | |
dashboard: a token handed over to another member's dashboard
Opening another member's dashboard passes a token reading only, for
five minutes, in the URL's fragment; its login page begins a session
with it. Tokens may be asked for with a shorter lifetime.
Auth plan M3 (hand-off).
Diffstat (limited to 'src/api/dashboard/login.html')
| -rw-r--r-- | src/api/dashboard/login.html | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/api/dashboard/login.html b/src/api/dashboard/login.html index 77668ee..e09d31c 100644 --- a/src/api/dashboard/login.html +++ b/src/api/dashboard/login.html @@ -73,6 +73,24 @@ document.getElementById("token").addEventListener("submit", async event => { why.textContent = ""; try { await begin(event.target.token.value.trim()); } catch (error) { failed(error); } }); +// Opened from another member's dashboard (`handOff`), sent here for want of a session: +// its token, reading only, begins one; the rest goes on to the dashboard. +(async () => { + const HAND_OFF = "#continuum="; + if (!location.hash.startsWith(HAND_OFF)) return; + const fragment = location.hash; + try { history.replaceState(null, "", location.pathname + location.search); } catch (_) {} + let handed; + try { handed = JSON.parse(decodeURIComponent(fragment.slice(HAND_OFF.length))); } catch (_) { return; } + if (!handed || typeof handed.token !== "string") return; + try { + await call("auth/session", "POST", "Bearer " + handed.token); + delete handed.token; + location.replace("admin/dashboard" + HAND_OFF + encodeURIComponent(JSON.stringify(handed))); + } catch (error) { + why.textContent = "The token handed over isn't taken (" + error.message + "): log in."; + } +})(); document.getElementById("out").addEventListener("click", async () => { await fetch("auth/session", { method: "DELETE", credentials: "same-origin" }).catch(() => {}); why.textContent = "Logged out of this browser."; |
