memos/web/src/auth-state.ts

74 lines
2.5 KiB
TypeScript

// Access token storage using sessionStorage for persistence across page refreshes
// sessionStorage is cleared when the tab/window is closed, providing reasonable security
// while avoiding unnecessary token refreshes on page reload
let accessToken: string | null = null;
let tokenExpiresAt: Date | null = null;
const SESSION_TOKEN_KEY = "memos_access_token";
const SESSION_EXPIRES_KEY = "memos_token_expires_at";
export const getAccessToken = (): string | null => {
// If not in memory, try to restore from sessionStorage
if (!accessToken) {
try {
const storedToken = sessionStorage.getItem(SESSION_TOKEN_KEY);
const storedExpires = sessionStorage.getItem(SESSION_EXPIRES_KEY);
if (storedToken && storedExpires) {
const expiresAt = new Date(storedExpires);
// Only restore if token hasn't expired
if (expiresAt > new Date()) {
accessToken = storedToken;
tokenExpiresAt = expiresAt;
} else {
// Token expired, clean up sessionStorage
sessionStorage.removeItem(SESSION_TOKEN_KEY);
sessionStorage.removeItem(SESSION_EXPIRES_KEY);
}
}
} catch (e) {
// sessionStorage might not be available (e.g., in some privacy modes)
console.warn("Failed to access sessionStorage:", e);
}
}
return accessToken;
};
export const setAccessToken = (token: string | null, expiresAt?: Date): void => {
accessToken = token;
tokenExpiresAt = expiresAt || null;
try {
if (token && expiresAt) {
// Store in sessionStorage for persistence across page refreshes
sessionStorage.setItem(SESSION_TOKEN_KEY, token);
sessionStorage.setItem(SESSION_EXPIRES_KEY, expiresAt.toISOString());
} else {
// Clear sessionStorage if token is being cleared
sessionStorage.removeItem(SESSION_TOKEN_KEY);
sessionStorage.removeItem(SESSION_EXPIRES_KEY);
}
} catch (e) {
// sessionStorage might not be available (e.g., in some privacy modes)
console.warn("Failed to write to sessionStorage:", e);
}
};
export const isTokenExpired = (): boolean => {
if (!tokenExpiresAt) return true;
// Consider expired 30 seconds before actual expiry for safety
return new Date() >= new Date(tokenExpiresAt.getTime() - 30000);
};
export const clearAccessToken = (): void => {
accessToken = null;
tokenExpiresAt = null;
try {
sessionStorage.removeItem(SESSION_TOKEN_KEY);
sessionStorage.removeItem(SESSION_EXPIRES_KEY);
} catch (e) {
console.warn("Failed to clear sessionStorage:", e);
}
};