/** * Cross-origin / same-site auth session bridge (presentation only). * * Threat model (P1): the session bearer must never transit a query string or * live in web storage / a non-HttpOnly cookie. URLs may carry only a * single-use `bridge_code`. App-origin GET exchange sets an HttpOnly * SameSite session cookie. Issuance and consume live on Athena JS * `/session/bridge/*` — this module must not store tokens. * * `auth.getSession()` may still return a token to JavaScript for same-page * Authorization on cross-origin client calls. That in-memory use is an * explicit remaining decision — do not persist it in the URL or web storage. * * Wire the route handlers under something like `/api/auth/bridge-session`. * * @deprecated LEGACY_BEARER_BRIDGE — query-string bearers, web storage, and * JS-readable pending cookies are forbidden. Use `bridge_code` + native * issue/exchange. */ /** Marker for T-BRIDGE-010: the bearer-in-URL bridge is retired. */ export declare const LEGACY_BEARER_BRIDGE: "deprecated"; /** HttpOnly Athena Auth session cookie names observed on the wire. */ export declare const ATHENA_AUTH_SESSION_COOKIE_NAMES: readonly ["athena-auth.session_token", "athena-auth.session-token"]; /** Default App Router path for the bridge handlers. */ export declare const DEFAULT_SESSION_BRIDGE_PATH = "/api/auth/bridge-session"; /** Default post-bridge redirect when none is provided. */ export declare const DEFAULT_SESSION_BRIDGE_REDIRECT = "/settings/account"; /** Query key for the one-time exchange code (never the session bearer). */ export declare const SESSION_BRIDGE_CODE_QUERY = "bridge_code"; /** Documented native code lifetime (server TTL is authoritative). */ export declare const SESSION_BRIDGE_CODE_TTL_MS = 30000; export interface SessionBridgeExchangeResult { expiresAt?: string; sessionToken: string; } export interface SessionBridgeExchangeInput { bridgeCode: string; destinationOrigin: string; } export interface SessionBridgeRouteOptions { /** Public path used when building bridge URLs (default `/api/auth/bridge-session`). */ bridgePath?: string; /** Default relative redirect when `redirectTo` is missing/invalid. */ defaultRedirectTo?: string; /** * Server-side consume. Must call native `POST /session/bridge/exchange` * (or an equivalent store consume). Never mint or look up tokens locally. */ exchange?: (input: SessionBridgeExchangeInput, request: Request) => Promise; } export interface SessionBridgeCookieOptions { path?: string; sameSite?: "Lax" | "Strict" | "None"; secure?: boolean; } /** Resolve request protocol, honoring `x-forwarded-proto`. */ export declare function resolveRequestProtocol(request: Request): string; /** * Allow only same-origin relative paths for redirects (pathname + search + hash). */ export declare function resolveSafeRedirectTarget(rawValue: string | null | undefined, defaultRedirectTo?: string): string; /** Serialize a `Set-Cookie` header value. */ export declare function formatSetCookie(name: string, value: string, options?: { httpOnly?: boolean; maxAge?: number; path?: string; sameSite?: "Lax" | "Strict" | "None"; secure?: boolean; }): string; export declare function buildAthenaAuthSessionTokenSetCookie(token: string, options?: SessionBridgeCookieOptions): string; export declare function buildClearAthenaAuthSessionCookies(options?: SessionBridgeCookieOptions): string[]; /** Read the HttpOnly Athena Auth session token from a Cookie header. */ export declare function readAthenaAuthSessionTokenCookie(cookieHeader: string | null | undefined): string | undefined; /** * Build a same-origin bridge URL. The query may include `bridge_code` only — * never a session bearer. */ export declare function buildSessionBridgeUrl(input: { bridgeCode: string; bridgePath?: string; origin?: string; redirectTo: string; }): string; /** * Server/settings helper: bounce through GET exchange when `bridge_code` is * present. A legacy `token` search param is ignored (must not re-enter a URL). */ export declare function resolveSettingsSessionBridgeTarget(input: { bridgeCode?: string | string[] | null; bridgePath?: string; redirectTo: string; /** @deprecated Ignored. Do not put session bearers in search params. */ token?: string | string[] | null; }): string | undefined; /** * GET bridge: exchange `bridge_code` via the native callback, set an HttpOnly * session cookie, then redirect. Query `token` is ignored. */ export declare function handleSessionBridgeGet(request: Request, options?: SessionBridgeRouteOptions): Promise; /** * POST bridge: clear app-origin session cookies. A body token is ignored — * issuance is native `POST /session/bridge/issue` only. */ export declare function handleSessionBridgePost(request: Request, _options?: SessionBridgeRouteOptions): Promise; /** Convenience export map for App Router / fetch route handlers. */ export declare function createSessionBridgeHandlers(options?: SessionBridgeRouteOptions): { GET: (request: Request) => Promise; POST: (request: Request) => Promise; }; export interface IssuedNativeBridgeCode { code: string; destinationOrigin: string; expiresAt?: string; redirectPath: string; } /** Issue a one-time code on the auth origin (session cookie required). */ export declare function issueNativeSessionBridgeCode(input: { authBaseUrl: string; destinationOrigin: string; redirectPath: string; }): Promise; /** * After login on the auth origin, issue a native code then return an app-origin * GET URL that carries only `bridge_code`. */ export declare function appendIssuedBridgeCodeToNavigationTarget(target: string, options: { authBaseUrl: string; bridgePath?: string; origin?: string; }): Promise; /** Clear Athena Auth session cookies on the app origin via POST. */ export declare function clearSessionTokenFromRequestOrigin(bridgePath?: string): Promise; /** * Extract session token from Better Auth / Athena getSession-shaped results * (`{ data: { session: { token } } }` or `{ session: { token } }`). */ export declare function extractSessionTokenFromAuthResult(result: unknown): string | undefined; /** * Attach `Authorization: Bearer` under `fetchOptions.headers` for * client method calls that accept Better Auth-style option bags. * * In-memory only: callers must pass a token from `getSession()`, not from a * URL or durable browser storage. */ export declare function withAuthorizationFetchOptions(input: unknown, sessionToken: string): { fetchOptions: { headers: { Authorization: string; }; }; };