Files
emaui/libs/api/src/lib/session/index.ts

52 lines
1.7 KiB
TypeScript

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<string, string>;
} {
const token = state?.auth?.token ?? resolveTokenFromStorage();
return { token, sessionHeaders: {} };
}