mirror of
https://github.com/hansjone/netx.git
synced 2026-10-19 08:30:45 +08:00
fix(auth): sync logout across browser tabs
Listen for localStorage token changes so other open pages clear session state when one tab signs out. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b540ea21c1
commit
a3bdad5be1
2 changed files with 26 additions and 2 deletions
|
|
@ -7,7 +7,14 @@ import {
|
||||||
useState,
|
useState,
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { apiGet, apiPost, clearAuthToken, getAuthToken, setAuthToken } from "../services/api";
|
import {
|
||||||
|
AUTH_TOKEN_KEY,
|
||||||
|
apiGet,
|
||||||
|
apiPost,
|
||||||
|
clearAuthToken,
|
||||||
|
getAuthToken,
|
||||||
|
setAuthToken,
|
||||||
|
} from "../services/api";
|
||||||
|
|
||||||
export type AuthUser = {
|
export type AuthUser = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -62,6 +69,23 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||||
})();
|
})();
|
||||||
}, [refreshMe]);
|
}, [refreshMe]);
|
||||||
|
|
||||||
|
// Other tabs keep React auth state until they hear localStorage change.
|
||||||
|
// `storage` fires only in *other* documents — used to sync logout/login.
|
||||||
|
useEffect(() => {
|
||||||
|
const onStorage = (ev: StorageEvent) => {
|
||||||
|
if (ev.storageArea && ev.storageArea !== localStorage) return;
|
||||||
|
if (ev.key !== null && ev.key !== AUTH_TOKEN_KEY) return;
|
||||||
|
if (ev.key === null || ev.newValue == null || ev.newValue === "") {
|
||||||
|
setToken(null);
|
||||||
|
setUser(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void refreshMe();
|
||||||
|
};
|
||||||
|
window.addEventListener("storage", onStorage);
|
||||||
|
return () => window.removeEventListener("storage", onStorage);
|
||||||
|
}, [refreshMe]);
|
||||||
|
|
||||||
const login = useCallback(async (username: string, password: string) => {
|
const login = useCallback(async (username: string, password: string) => {
|
||||||
const data = await apiPost<{ access_token: string; user: AuthUser }>("/v1/auth/login", {
|
const data = await apiPost<{ access_token: string; user: AuthUser }>("/v1/auth/login", {
|
||||||
username,
|
username,
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import type {
|
||||||
TopologyMapItem,
|
TopologyMapItem,
|
||||||
} from "../types";
|
} from "../types";
|
||||||
|
|
||||||
const AUTH_TOKEN_KEY = "netx_access_token";
|
export const AUTH_TOKEN_KEY = "netx_access_token";
|
||||||
|
|
||||||
export const getAuthToken = (): string | null => {
|
export const getAuthToken = (): string | null => {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue