import Cookies from "js-cookie"; export const SESSION_HEADER_KEYS = { tenantId: "x-tenant-id", organizationUnitId: "x-organization-unit-id", currentPositionId: "x-current-position-id", currentProjectId: "x-current-project-id", } as const; /** * Which app this bundle is, so it reads its own session and no one else's. * * Set by each app's store via `configureSessionScope`. Cookies ignore the * port, so `localhost:3000` and `localhost:4201` share one jar: without a * scope the backoffice would happily authenticate as whoever last signed into * the portal, and render a staff console with an applicant's permissions. */ let scopedTokenKey: string | undefined; export function configureSessionScope(prefix: string): void { scopedTokenKey = `${prefix}-auth-token`; } /** Legacy, pre-prefix sessions. Read only when the scoped key is empty. */ const LEGACY_TOKEN_KEY = "auth-token"; export function resolveTokenFromStorage(): string | undefined { // Only this app's key, then the legacy unprefixed one. Never another app's: // falling through to a sibling's token is how a backoffice tab ends up // holding a portal session. const keys = scopedTokenKey ? [scopedTokenKey, LEGACY_TOKEN_KEY] : [LEGACY_TOKEN_KEY]; for (const key of keys) { // cookie first, then localStorage (legacy pre-migration sessions) const cookie = Cookies.get(key); if (cookie) return cookie; const stored = localStorage.getItem(key); if (stored) return stored; } return undefined; } export function resolveSessionContext(state?: { auth?: { token?: string } }): { token: string | undefined; sessionHeaders: Record; } { const token = state?.auth?.token ?? resolveTokenFromStorage(); return { token, sessionHeaders: {} }; }