aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/dashboard/dashboard.html
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-07 22:35:22 +0100
committertv <tv@krebsco.de>2026-11-07 22:35:22 +0100
commitb99e7ddf38233120ea19485968c12c5548e7fa61 (patch)
tree0dbd1fca28e979d76b54d38c446a70e082da9595 /src/api/dashboard/dashboard.html
parentc296fe8b2532f40c9a1f839ebdac2449e38342d5 (diff)
auth: a login page and browser sessions
GET /login without authentication: log in by password or with a token (from a login by key). POST/DELETE /auth/session keep the token as an HttpOnly, SameSite=Strict cookie; the dashboard sends a browser without a user there and renews the session while open. Auth plan M2/M3 (browsers).
Diffstat (limited to 'src/api/dashboard/dashboard.html')
-rw-r--r--src/api/dashboard/dashboard.html11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html
index 300f4fe..8146f32 100644
--- a/src/api/dashboard/dashboard.html
+++ b/src/api/dashboard/dashboard.html
@@ -2276,8 +2276,9 @@ function unapplySubscriptions() {
}
overlaid.clear();
}
-// Tokens: this page's, from logging in on this node (the browser's password for it, or
-// the proxy's), and a narrower one, reading the member list only, to send to others.
+// Tokens: this page's, from logging in on this node (the browser's password for it, the
+// proxy's, or the session the login page began), and a narrower one, reading the member
+// list only, to send to others.
// Each refreshed half way through its life.
let token = null, narrowToken = null, tokenWhy = "not logged in yet", tokenTimer = null;
const READ_MEMBERS = [{ path: ["_continuum", "members"], rights: ["read"] }];
@@ -2293,9 +2294,11 @@ async function tokenCall(url, bearer, body) {
async function obtainTokens() {
clearTimeout(tokenTimer);
try {
+ // Refreshed as the session (`POST /auth/session`), whose cookie lets the page in;
+ // the first: by the browser's password or the proxy's, else by that cookie.
token = token && token.expiresAt > Date.now() + 60000
- ? await tokenCall("../auth/refresh", token.token)
- : await tokenCall("../auth/login");
+ ? await tokenCall("../auth/session", token.token)
+ : await tokenCall("../auth/login").catch(() => tokenCall("../auth/session"));
narrowToken = await tokenCall("../auth/refresh", token.token, { limit: READ_MEMBERS });
tokenWhy = null;
const life = Math.min(token.expiresAt, narrowToken.expiresAt) - Date.now();