import Cookies from "js-cookie"; function getCookieExpiresDays(): number { if (typeof window === "undefined") return 1; try { const rememberMe = localStorage.getItem("rememberMe") === "true"; return rememberMe ? 15 : 1; } catch { return 1; } } const isHttps = typeof window !== "undefined" && window.location.protocol === "https:"; function removeCookieCompletely(name: string) { if (typeof document === "undefined") return; const paths = ["/", ""]; const samesites: Array<"strict" | "lax" | "none" | undefined> = [ "strict", "lax", undefined, ]; const secures = [true, false]; for (const path of paths) { for (const secure of secures) { for (const sameSite of samesites) { try { Cookies.remove(name, { path, secure, sameSite }); } catch { // ignore } } } } const pastDate = "Thu, 01 Jan 1970 00:00:00 GMT"; const expireStrings = [ `${name}=; path=/; expires=${pastDate}; max-age=0`, `${name}=; path=/; expires=${pastDate}; max-age=0; SameSite=Strict`, `${name}=; path=/; expires=${pastDate}; max-age=0; SameSite=Strict; Secure`, `${name}=; path=/; expires=${pastDate}; max-age=0; SameSite=Lax`, `${name}=; path=/; expires=${pastDate}; max-age=0; SameSite=Lax; Secure`, `${name}=; expires=${pastDate}; max-age=0`, ]; try { const domain = window.location.hostname; const domainParts = domain.split("."); if (domainParts.length > 1) { expireStrings.push( `${name}=; path=/; domain=${domain}; expires=${pastDate}; max-age=0` ); expireStrings.push( `${name}=; path=/; domain=.${domain}; expires=${pastDate}; max-age=0` ); } } catch { // ignore } expireStrings.forEach((str) => { try { document.cookie = str; } catch { // ignore } }); } interface Backend { get(k: string): string | null; set(k: string, v: string): void; remove(k: string): void; } const localStore: Backend = { get: (k) => localStorage.getItem(k), set: (k, v) => localStorage.setItem(k, v), remove: (k) => localStorage.removeItem(k), }; const cookieStore: Backend = { get: (k) => Cookies.get(k) ?? null, set: (k, v) => Cookies.set(k, v, { path: "/", secure: isHttps, sameSite: "strict", expires: getCookieExpiresDays(), }), remove: (k) => removeCookieCompletely(k), }; const AUTH_KEY_NAMES = [ "auth-token", "refresh-token", "auth-user", "profile-id", "current-profile", ]; const KNOWN_PREFIXES = ["ema-backoffice", "ema-portal", "ema-auth", ""]; let _prefix = "ema-auth"; let backend: Backend = localStore; export function configureAuthStorage(prefix: string, useCookies = false) { _prefix = prefix; backend = useCookies ? cookieStore : localStore; if (useCookies) { // drop pre-migration localStorage leftovers so tokens live in cookies only AUTH_KEY_NAMES.forEach((k) => localStorage.removeItem(`${prefix}-${k}`)); } } function key(k: string) { return `${_prefix}-${k}`; } export const authStorage = { getToken: () => backend.get(key("auth-token")) ?? undefined, setToken: (token: string) => backend.set(key("auth-token"), token), getRefreshToken: () => backend.get(key("refresh-token")) ?? undefined, setRefreshToken: (t: string) => backend.set(key("refresh-token"), t), getUser: (): T | null => { try { return JSON.parse(backend.get(key("auth-user")) ?? "null") as T | null; } catch { return null; } }, setUser: (u: T) => backend.set(key("auth-user"), JSON.stringify(u)), getProfileId: () => backend.get(key("profile-id")) ?? undefined, setProfileId: (id: string) => backend.set(key("profile-id"), id), getProfile: (): T | null => { try { return JSON.parse( backend.get(key("current-profile")) ?? "null", ) as T | null; } catch { return null; } }, setProfile: (p: T) => backend.set(key("current-profile"), JSON.stringify(p)), removeProfile: () => backend.remove(key("current-profile")), clear: () => { const prefixes = Array.from(new Set([_prefix, ...KNOWN_PREFIXES])); prefixes.forEach((p) => { AUTH_KEY_NAMES.forEach((k) => { const fullKey = p ? `${p}-${k}` : k; removeCookieCompletely(fullKey); try { localStorage.removeItem(fullKey); } catch { // ignore } }); }); try { localStorage.removeItem("rememberMe"); } catch { // ignore } try { if (typeof Cookies !== "undefined") { const allCookies = Cookies.get(); if (allCookies) { Object.keys(allCookies).forEach((name) => { removeCookieCompletely(name); }); } } } catch { // ignore } }, };