fix: prevent stale session warning redirect loops
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
let lastConfirmedAt = Date.now();
|
||||
let warningVisible = false;
|
||||
let keepaliveInFlight = false;
|
||||
let timeoutCheckInFlight = false;
|
||||
let redirectInFlight = false;
|
||||
|
||||
function getCsrfToken() {
|
||||
const cookie = document.cookie
|
||||
@@ -44,11 +46,22 @@
|
||||
status.textContent = "";
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
if (redirectInFlight) return;
|
||||
redirectInFlight = true;
|
||||
window.location.href = config.loginUrl;
|
||||
}
|
||||
|
||||
function readStoredConfirmedAt() {
|
||||
try {
|
||||
const raw = window.localStorage.getItem(storageKey);
|
||||
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
||||
return Number.isFinite(parsed) ? parsed : null;
|
||||
if (!Number.isFinite(parsed)) return null;
|
||||
const maxAgeMs = config.idleTimeoutSeconds * 1000;
|
||||
if (Date.now() - parsed >= maxAgeMs) {
|
||||
return null;
|
||||
}
|
||||
return parsed;
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
@@ -95,8 +108,9 @@
|
||||
credentials: "same-origin",
|
||||
body: JSON.stringify({ keepalive: true }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
window.location.href = config.loginUrl;
|
||||
const contentType = (response.headers.get("content-type") || "").toLowerCase();
|
||||
if (!response.ok || response.redirected || !contentType.includes("application/json")) {
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
syncConfirmedAt(Date.now(), "self");
|
||||
@@ -108,12 +122,46 @@
|
||||
hideStatus();
|
||||
}, 1200);
|
||||
} catch (_error) {
|
||||
window.location.href = config.loginUrl;
|
||||
redirectToLogin();
|
||||
} finally {
|
||||
keepaliveInFlight = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSessionOrRedirect() {
|
||||
if (timeoutCheckInFlight || keepaliveInFlight || redirectInFlight) return;
|
||||
timeoutCheckInFlight = true;
|
||||
try {
|
||||
const response = await fetch(config.keepaliveUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRFToken": getCsrfToken(),
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
},
|
||||
credentials: "same-origin",
|
||||
body: JSON.stringify({ keepalive: true, timeout_check: true }),
|
||||
});
|
||||
const contentType = (response.headers.get("content-type") || "").toLowerCase();
|
||||
if (!response.ok || response.redirected || !contentType.includes("application/json")) {
|
||||
try {
|
||||
window.localStorage.removeItem(storageKey);
|
||||
} catch (_error) {
|
||||
// Ignore storage cleanup failures.
|
||||
}
|
||||
redirectToLogin();
|
||||
return;
|
||||
}
|
||||
syncConfirmedAt(Date.now(), "self");
|
||||
hideWarning();
|
||||
hideStatus();
|
||||
} catch (_error) {
|
||||
redirectToLogin();
|
||||
} finally {
|
||||
timeoutCheckInFlight = false;
|
||||
}
|
||||
}
|
||||
|
||||
const storedConfirmedAt = readStoredConfirmedAt();
|
||||
if (storedConfirmedAt) {
|
||||
lastConfirmedAt = storedConfirmedAt;
|
||||
@@ -149,7 +197,7 @@
|
||||
const elapsedSeconds = Math.floor((Date.now() - lastConfirmedAt) / 1000);
|
||||
const secondsLeft = config.idleTimeoutSeconds - elapsedSeconds;
|
||||
if (secondsLeft <= 0) {
|
||||
window.location.href = config.loginUrl;
|
||||
confirmSessionOrRedirect();
|
||||
return;
|
||||
}
|
||||
if (secondsLeft <= warningLeadSeconds) {
|
||||
|
||||
Reference in New Issue
Block a user