v3: fixed authorization bug with stale tokens, fixed private dump access bug, various small fixes across the app
Some checks failed
Build and Publish Docker Image / build-and-push (push) Failing after 20s
Some checks failed
Build and Publish Docker Image / build-and-push (push) Failing after 20s
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { type ReactNode, useEffect, useState } from "react";
|
||||
|
||||
import { AuthContext, type AuthContextValue } from "./AuthContext.ts";
|
||||
|
||||
import { type AuthResponse, deserializeAuthResponse } from "../model.ts";
|
||||
import { API_URL } from "../config/api.ts";
|
||||
|
||||
function isTokenExpired(token: string): boolean {
|
||||
try {
|
||||
@@ -33,6 +34,43 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
return parsed;
|
||||
});
|
||||
|
||||
// The `exp` pre-check above only catches expiry; it cannot detect a token the
|
||||
// server rejects for another reason (e.g. a changed GERBEUR_JWT_SECRET, which
|
||||
// leaves the signature invalid but the token unexpired). Ask the server — the
|
||||
// only authority on validity — and clear the session if it returns 401, so the
|
||||
// UI never shows a false "logged in" state. Re-check when the tab regains
|
||||
// focus to catch tokens invalidated by a server restart while we were away.
|
||||
const token = authResponse?.token;
|
||||
useEffect(() => {
|
||||
if (!token) return;
|
||||
|
||||
const validate = async () => {
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/api/users/me`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
cache: "no-store",
|
||||
});
|
||||
if (res.status === 401) {
|
||||
localStorage.removeItem("authResponse");
|
||||
setAuthResponse(null);
|
||||
}
|
||||
} catch {
|
||||
// Network error — don't log out an offline user; only an explicit 401 clears the session.
|
||||
}
|
||||
};
|
||||
|
||||
validate();
|
||||
const onVisible = () => {
|
||||
if (document.visibilityState === "visible") validate();
|
||||
};
|
||||
globalThis.addEventListener("focus", validate);
|
||||
document.addEventListener("visibilitychange", onVisible);
|
||||
return () => {
|
||||
globalThis.removeEventListener("focus", validate);
|
||||
document.removeEventListener("visibilitychange", onVisible);
|
||||
};
|
||||
}, [token]);
|
||||
|
||||
const value: AuthContextValue = { authResponse, setAuthResponse };
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user