@hyper.authio/bff 0.8.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -2
- package/dist/index.cjs +51 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +51 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/claims.ts","../src/http.ts","../src/options.ts","../src/protection.ts","../src/remote-api.ts","../src/session-locks.ts","../src/session-store.ts","../src/bff.ts"],"names":["AuthioConfigurationError","AuthioPrompts","target","randomBytes","logout","timingSafeEqual"],"mappings":"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","file":"index.js","sourcesContent":["import { AuthioClaimTypes, AuthioResourceAccessClaims, parseResourceAccess, resourceAccessSourceOf } from \"@hyper.authio/client\";\n\n/**\n * The claim types `/bff/user` adds to the person's claims.\n */\nexport const AuthioBffClaimTypes = {\n /** Seconds until the BFF session expires. */\n SessionExpiresIn: \"bff:session_expires_in\",\n /** The URL the SPA navigates to in order to log out; it carries the session's `sid`. */\n LogoutUrl: \"bff:logout_url\",\n /** One Authio role the person holds (flattened from the `*_resource_access` claims). */\n Role: \"role\",\n /** One permission the person holds, as `{resource}:{method}` (flattened from the `*_resource_access` claims). */\n Permission: \"permission\",\n} as const;\n\n/**\n * One entry of the `/bff/user` answer: a string value, or a number for `bff:session_expires_in`.\n */\nexport interface AuthioBffClaim {\n readonly type: string;\n readonly value: string | number;\n}\n\n/**\n * The JSON body of a BFF refusal, shaped like an OAuth error.\n */\nexport interface AuthioBffError {\n readonly error: string;\n readonly error_description?: string;\n}\n\nconst accessTokenClaimTypes = new Set<string>([\n ...Object.keys(AuthioResourceAccessClaims),\n AuthioClaimTypes.OrganizationId,\n AuthioClaimTypes.OrganizationAlias,\n AuthioClaimTypes.AccountId,\n]);\n\nconst protocolClaimTypes = new Set([\"nonce\", \"aud\", \"azp\", \"iss\", \"iat\", \"nbf\", \"exp\", \"at_hash\", \"c_hash\", \"ipaddr\", \"platf\", \"ver\"]);\n\n/**\n * The session's claims from a validated ID token: every claim except the protocol ones the OpenID Connect handler of\n * ASP.NET Core drops (`nonce`, `aud`, `azp`, `iss`, `iat`, `nbf`, `exp`, `at_hash`…).\n *\n * @internal\n */\nexport function toSessionClaims(idToken: Readonly<Record<string, unknown>> | undefined, fallbackSubject: string | undefined): Record<string, unknown> {\n const claims: Record<string, unknown> = {};\n\n for (const [type, value] of Object.entries(idToken ?? {})) if (!protocolClaimTypes.has(type) && value !== undefined && value !== null) claims[type] = value;\n\n if (claims.sub === undefined && fallbackSubject) claims.sub = fallbackSubject;\n\n return claims;\n}\n\n/**\n * Adds the UserInfo claims the session does not carry yet.\n *\n * @internal\n */\nexport function mergeUserInfo(claims: Record<string, unknown>, userInfo: Readonly<Record<string, unknown>>): void {\n for (const [type, value] of Object.entries(userInfo)) if (claims[type] === undefined && value !== undefined && value !== null) claims[type] = value;\n}\n\n/**\n * Replaces the claims only the access token carries (the seven `*_resource_access`, `org_id`, `org_alias`,\n * `account_id`) with those of the access token's verified payload (`AuthioClient.readAccessTokenClaims`). Without a\n * verified payload (an opaque token, or one the BFF cannot open or verify) nothing changes.\n *\n * @internal\n */\nexport function replaceAccessTokenClaims(claims: Record<string, unknown>, payload: Readonly<Record<string, unknown>> | undefined): void {\n if (!payload) return;\n\n for (const type of Object.keys(claims)) if (accessTokenClaimTypes.has(type)) delete claims[type];\n for (const [type, value] of Object.entries(payload)) if (accessTokenClaimTypes.has(type) && value !== undefined && value !== null) claims[type] = value;\n}\n\n/**\n * Builds the `/bff/user` answer: every claim of the session but the raw `*_resource_access` JSON (arrays as one entry\n * per element, other values as text), then one `role` per Authio role and one `permission` per grant, then\n * `bff:session_expires_in` and `bff:logout_url`.\n *\n * @internal\n */\nexport function toAuthioBffClaims(claims: Readonly<Record<string, unknown>>, sessionExpiresIn: number, logoutUrl: string): AuthioBffClaim[] {\n const entries: AuthioBffClaim[] = [];\n const seen = new Set<string>();\n const add = (type: string, value: string) => {\n const key = `${type}\\u0000${value}`;\n\n if (seen.has(key)) return;\n\n seen.add(key);\n entries.push({ type, value });\n };\n\n for (const [type, value] of Object.entries(claims)) {\n if (resourceAccessSourceOf(type)) continue;\n\n for (const item of Array.isArray(value) ? value : [value]) if (item !== undefined && item !== null) add(type, toText(item));\n }\n\n const access = parseResourceAccess(claims);\n\n for (const role of access.roles) add(AuthioBffClaimTypes.Role, role);\n for (const [resource, methods] of Object.entries(access.permissions)) for (const method of methods) add(AuthioBffClaimTypes.Permission, `${resource}:${method}`);\n\n entries.push({ type: AuthioBffClaimTypes.SessionExpiresIn, value: sessionExpiresIn });\n entries.push({ type: AuthioBffClaimTypes.LogoutUrl, value: logoutUrl });\n\n return entries;\n}\n\nfunction toText(value: unknown): string {\n return typeof value === \"string\" ? value : typeof value === \"object\" ? JSON.stringify(value) : String(value);\n}\n","import type { Request, Response } from \"express\";\nimport type { AuthioBffCookieSameSite } from \"./options.js\";\n\n/**\n * Reads the request's cookies, first value per name, without needing `cookie-parser`.\n *\n * @internal\n */\nexport function readCookies(request: Request): Map<string, string> {\n const cookies = new Map<string, string>();\n\n for (const part of (request.headers.cookie ?? \"\").split(\";\")) {\n const separator = part.indexOf(\"=\");\n\n if (separator <= 0) continue;\n\n const name = part.slice(0, separator).trim();\n\n if (!name || cookies.has(name)) continue;\n\n let value = part.slice(separator + 1).trim();\n\n if (value.startsWith('\"') && value.endsWith('\"') && value.length >= 2) value = value.slice(1, -1);\n\n try {\n cookies.set(name, decodeURIComponent(value));\n } catch {\n cookies.set(name, value);\n }\n }\n\n return cookies;\n}\n\n/**\n * Adds a `Set-Cookie` header: `HttpOnly`, `Secure`, `Path=/`, no `Domain`; a session cookie unless `maxAge` (seconds)\n * is given, deleted when it is 0.\n *\n * @internal\n */\nexport function setCookie(response: Response, name: string, value: string, sameSite: AuthioBffCookieSameSite, maxAge?: number): void {\n if (response.headersSent) return;\n\n const attributes = [\n `${name}=${encodeURIComponent(value)}`,\n \"Path=/\",\n ...(maxAge === undefined ? [] : [`Max-Age=${Math.max(0, Math.floor(maxAge))}`]),\n ...(maxAge === 0 ? [\"Expires=Thu, 01 Jan 1970 00:00:00 GMT\"] : []),\n \"HttpOnly\",\n \"Secure\",\n `SameSite=${sameSite === \"strict\" ? \"Strict\" : \"Lax\"}`,\n ];\n\n response.append(\"Set-Cookie\", attributes.join(\"; \"));\n}\n\n/**\n * Answers with a JSON error (`{ error, error_description }`) and `Cache-Control: no-store`, unless the response\n * already started.\n *\n * @internal\n */\nexport function sendError(response: Response, status: number, error: string, description?: string): void {\n if (response.headersSent) return;\n\n response.status(status).set(\"Cache-Control\", \"no-store\").json(description ? { error, error_description: description } : { error });\n}\n\n/**\n * Whether the request carries the anti-forgery header exactly once, with the expected value.\n *\n * @internal\n */\nexport function hasAntiForgeryHeader(request: Request, name: string, value: string): boolean {\n const lower = name.toLowerCase();\n let count = 0;\n let matched = false;\n\n for (let index = 0; index < request.rawHeaders.length; index += 2) {\n if (request.rawHeaders[index]?.toLowerCase() !== lower) continue;\n\n count += 1;\n matched = request.rawHeaders[index + 1] === value;\n }\n\n return count === 1 && matched;\n}\n\n/**\n * The query parameters of the request, first value per name, read from the URL rather than Express's parser.\n *\n * @internal\n */\nexport function readQuery(request: Request): URLSearchParams {\n return new URL(request.originalUrl || request.url, \"http://localhost\").searchParams;\n}\n\n/**\n * The public origin and mount path of the request: `{protocol}://{host}{baseUrl}`. Honours `trust proxy` for the\n * protocol.\n *\n * @internal\n */\nexport function requestBase(request: Request): string {\n return `${request.protocol}://${request.get(\"host\") ?? \"localhost\"}${request.baseUrl ?? \"\"}`;\n}\n\n/**\n * Appends a query parameter to a local URL.\n *\n * @internal\n */\nexport function withQueryParameter(url: string, name: string, value: string): string {\n const hash = url.indexOf(\"#\");\n const base = hash >= 0 ? url.slice(0, hash) : url;\n const fragment = hash >= 0 ? url.slice(hash) : \"\";\n\n return `${base}${base.includes(\"?\") ? \"&\" : \"?\"}${encodeURIComponent(name)}=${encodeURIComponent(value)}${fragment}`;\n}\n\n/**\n * Reads a form field of a urlencoded body, whether a body parser already ran or not.\n *\n * @internal\n */\nexport async function readFormField(request: Request, field: string, maxBytes = 64 * 1024): Promise<string | undefined> {\n const parsed = (request as Request & { body?: unknown }).body;\n\n if (parsed && typeof parsed === \"object\" && !Buffer.isBuffer(parsed)) {\n const value = (parsed as Record<string, unknown>)[field];\n\n if (typeof value === \"string\") return value;\n }\n\n if (!(request.headers[\"content-type\"] ?? \"\").toLowerCase().startsWith(\"application/x-www-form-urlencoded\")) return undefined;\n\n const text = Buffer.isBuffer(parsed) ? parsed.toString(\"utf8\") : typeof parsed === \"string\" ? parsed : request.readableEnded ? undefined : await readText(request, maxBytes);\n\n return text === undefined ? undefined : (new URLSearchParams(text).get(field) ?? undefined);\n}\n\nfunction readText(request: Request, maxBytes: number): Promise<string | undefined> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n let done = false;\n\n request.on(\"data\", (chunk: Buffer) => {\n if (done) return;\n\n size += chunk.byteLength;\n\n if (size > maxBytes) {\n done = true;\n request.pause();\n resolve(undefined);\n return;\n }\n\n chunks.push(chunk);\n });\n request.on(\"end\", () => {\n if (!done) resolve(Buffer.concat(chunks).toString(\"utf8\"));\n });\n request.on(\"error\", reject);\n });\n}\n","import { AuthioConfigurationError, AuthioPrompts, type AuthioClient, type AuthioClientOptions, type AuthioPrompt } from \"@hyper.authio/client\";\nimport type { AuthioBffSessionStore } from \"./session-store.js\";\n\n/**\n * Default names and values of the Authio BFF, the same as `Authio.AspNetCore.Bff`'s.\n */\nexport const AuthioBffDefaults = {\n /** The session cookie name. `__Host-` makes browsers refuse it unless it is `Secure`, has `Path=/` and no `Domain`. */\n CookieName: \"__Host-authio\",\n /** The route prefix of the BFF endpoints. */\n EndpointPrefix: \"/bff\",\n /** The anti-forgery header the SPA sends on every API call. */\n AntiForgeryHeaderName: \"X-CSRF\",\n /** The value the anti-forgery header carries. */\n AntiForgeryHeaderValue: \"1\",\n /** The redirect path Authio sends the person back to after sign-in. */\n CallbackPath: \"/signin-oidc\",\n /** The redirect path Authio sends the person back to after sign-out. */\n SignedOutCallbackPath: \"/signout-callback-oidc\",\n /** The `source` of the message the silent-login page posts to its parent window. */\n SilentLoginMessageSource: \"authio-bff-silent-login\",\n /** The prefix of the keys sessions are stored under. */\n SessionKeyPrefix: \"authio-bff:\",\n /** Seconds a session lasts without activity (8 hours). */\n SessionLifetime: 8 * 60 * 60,\n /** Seconds between two checks of the Authio session (5 minutes). */\n SessionValidationInterval: 5 * 60,\n /** Seconds a sign-in may take between the login request and the callback (15 minutes). */\n LoginLifetime: 15 * 60,\n /** The scopes asked for at sign-in; `offline_access` gives the BFF a refresh token. */\n Scopes: Object.freeze([\"openid\", \"profile\", \"email\", \"offline_access\"]) as readonly string[],\n} as const;\n\n/**\n * How the BFF checks that the person's Authio session is still alive: `none`, or `introspection` of the session's\n * refresh token (its access token when there is none) every `sessionValidationInterval`.\n */\nexport type AuthioBffSessionValidation = \"none\" | \"introspection\";\n\n/**\n * The `SameSite` mode of the session cookie.\n */\nexport type AuthioBffCookieSameSite = \"lax\" | \"strict\";\n\n/**\n * Settings of the Authio BFF. The client itself (`issuer` or `authority` + `realm`, `clientId`, `clientSecret`,\n * `tokenEndpointAuthMethod`, `clientPrivateKey`, `clientEncryptionKey`, `checks`, `codeChallengeMethod`,\n * `idTokenSignedResponseAlg`, `tokenRefreshSkew`…) takes the names of `conformance/options.md` and mirrors the client\n * as registered in Authio: an option left out is off. The BFF's own settings are those of `Authio.AspNetCore.Bff`\n * (`Authio:Bff`).\n */\nexport interface AuthioBffOptions extends Partial<AuthioClientOptions> {\n /**\n * An Authio client to use instead of creating one from the connection and credential options above. The BFF still\n * reads `tokenRefreshSkew`, `checks`, `codeChallengeMethod`, `responseMode`, `redirectUri` and\n * `postLogoutRedirectUri` from these options; tokens are validated and decrypted by the client.\n */\n client?: AuthioClient;\n /**\n * Secrets the session cookie is signed with and the stored sessions and sign-in cookies are encrypted with, at least\n * 32 characters each. The first one signs and encrypts; every one is accepted, so a new secret can be put first and\n * the old one removed once the sessions it protects have expired.\n */\n cookieSecret: string | readonly string[];\n /** Where sessions live. Defaults to an in-memory store; give a shared one (Redis…) for several instances. */\n store?: AuthioBffSessionStore;\n /** The route prefix of the BFF endpoints. Defaults to `/bff`. */\n endpointPrefix?: string;\n /**\n * The scopes asked for at sign-in, sent as configured: without `openid` there is no ID token, and the session is\n * built from the access token (and UserInfo). Defaults to `openid profile email offline_access`.\n */\n scopes?: readonly string[];\n /** Adds the `roles` scope, so the session carries the `*_resource_access` claims flattened on `/bff/user`. */\n requestRoles?: boolean;\n /** Calls Authio's UserInfo endpoint after sign-in and adds its claims to the session. Defaults to `false`. */\n getClaimsFromUserInfoEndpoint?: boolean;\n /** The `organization` sent on every sign-in unless the login request names one. */\n organization?: string;\n /**\n * The `resource` (RFC 8707) sent on every sign-in unless the login request names one: the session's access token is\n * then addressed to that API. Keep `offline_access`, so the session check introspects the refresh token.\n */\n resource?: string;\n /** The resources a login request may ask for with `?resource=`; any other is refused with `400`. */\n allowedResources?: readonly string[];\n /** The `prompt` sent on every sign-in unless the login request names one. */\n prompt?: AuthioPrompt;\n /** The `ui_locales` sent on every sign-in and sign-out unless the request names one. */\n uiLocales?: string;\n /** The `max_age` (seconds) sent on every sign-in unless the login request names one. */\n maxAge?: number;\n /** Extra authorize parameters sent on every sign-in. */\n additionalAuthorizationParameters?: Readonly<Record<string, string>>;\n /** Refuses an authorization response without `iss` (RFC 9207). Defaults to `true`; Authio always sends it. */\n requireIssuerParameter?: boolean;\n /** The redirect path registered at Authio for sign-in. Defaults to `/signin-oidc`. */\n callbackPath?: string;\n /** The post-logout redirect path registered at Authio. Defaults to `/signout-callback-oidc`. */\n signedOutCallbackPath?: string;\n /** Where the browser lands after login or logout without a `returnUrl`. Must be local. Defaults to `/`. */\n defaultReturnUrl?: string;\n /** The session cookie name. Defaults to `__Host-authio`; it must start with `__Host-` or `__Secure-`. */\n cookieName?: string;\n /** The session cookie's `SameSite`: `lax` (default) or `strict`. */\n cookieSameSite?: AuthioBffCookieSameSite;\n /** Seconds a session lasts without activity. Defaults to 28800 (8 hours). */\n sessionLifetime?: number;\n /** Renews `sessionLifetime` on activity once half of it has passed. Defaults to `true`. */\n slidingExpiration?: boolean;\n /** How the Authio session is checked. Defaults to `introspection`. */\n sessionValidation?: AuthioBffSessionValidation;\n /** Seconds between two checks of the Authio session. Defaults to 300. */\n sessionValidationInterval?: number;\n /** Revokes the refresh token at Authio on logout. Defaults to `true`. */\n revokeRefreshTokenOnLogout?: boolean;\n /** The anti-forgery header API calls must carry. Defaults to `X-CSRF`. */\n antiForgeryHeaderName?: string;\n /** The value the anti-forgery header must carry. Defaults to `1`. */\n antiForgeryHeaderValue?: string;\n /** The prefix of the keys sessions are stored under. Defaults to `authio-bff:`. */\n sessionKeyPrefix?: string;\n /**\n * Serves `POST {endpointPrefix}/backchannel-logout`, which ends the sessions of the Authio session (`sid`) or person\n * (`sub`) a logout token names. Defaults to `true`; register that URL as the client's back-channel logout URI.\n */\n backChannelLogout?: boolean;\n /**\n * Serves `GET {endpointPrefix}/frontchannel-logout`, which Authio loads in an iframe when a session ends: it ends the\n * sessions of the `sid` it names (with `iss` checked), or the browser's own session when it names none. Defaults to\n * `false`; register that URL as the client's front-channel logout URI, with the session required.\n */\n frontChannelLogout?: boolean;\n /** Called with errors the BFF recovers from: a failed revocation, introspection or refresh, a refused logout token. */\n onError?: (error: unknown) => void;\n}\n\n/**\n * The BFF settings, resolved and validated.\n *\n * @internal\n */\nexport interface AuthioBffSettings {\n readonly cookieSecrets: readonly string[];\n readonly endpointPrefix: string;\n readonly scopes: readonly string[];\n readonly getClaimsFromUserInfoEndpoint: boolean;\n readonly organization: string | undefined;\n readonly resource: string | undefined;\n readonly allowedResources: readonly string[];\n readonly prompt: AuthioPrompt | undefined;\n readonly uiLocales: string | undefined;\n readonly maxAge: number | undefined;\n readonly additionalAuthorizationParameters: Readonly<Record<string, string>>;\n readonly requireIssuerParameter: boolean;\n readonly callbackPath: string;\n readonly signedOutCallbackPath: string;\n readonly defaultReturnUrl: string;\n readonly cookieName: string;\n readonly cookieSameSite: AuthioBffCookieSameSite;\n readonly sessionLifetimeMs: number;\n readonly slidingExpiration: boolean;\n readonly sessionValidation: AuthioBffSessionValidation;\n readonly sessionValidationIntervalMs: number;\n readonly revokeRefreshTokenOnLogout: boolean;\n readonly antiForgeryHeaderName: string;\n readonly antiForgeryHeaderValue: string;\n readonly sessionKeyPrefix: string;\n readonly backChannelLogout: boolean;\n readonly frontChannelLogout: boolean;\n readonly tokenRefreshSkewMs: number;\n readonly redirectUri: string | undefined;\n readonly postLogoutRedirectUri: string | undefined;\n readonly onError: (error: unknown) => void;\n}\n\n/**\n * Resolves the BFF settings, naming every problem at once.\n *\n * @throws AuthioConfigurationError listing what is wrong.\n * @internal\n */\nexport function resolveBffSettings(options: AuthioBffOptions): AuthioBffSettings {\n const problems: string[] = [];\n const cookieSecrets = (typeof options.cookieSecret === \"string\" ? [options.cookieSecret] : [...(options.cookieSecret ?? [])]).filter(\n (secret) => typeof secret === \"string\",\n );\n const settings: AuthioBffSettings = {\n cookieSecrets,\n endpointPrefix: `/${(options.endpointPrefix ?? AuthioBffDefaults.EndpointPrefix).replace(/^\\/+|\\/+$/g, \"\")}`,\n scopes: distinct([...(options.scopes ?? AuthioBffDefaults.Scopes), ...(options.requestRoles ? [\"roles\"] : [])]),\n getClaimsFromUserInfoEndpoint: options.getClaimsFromUserInfoEndpoint ?? false,\n organization: nonEmpty(options.organization),\n resource: nonEmpty(options.resource),\n allowedResources: [...(options.allowedResources ?? [])],\n prompt: options.prompt || undefined,\n uiLocales: nonEmpty(options.uiLocales),\n maxAge: options.maxAge,\n additionalAuthorizationParameters: { ...options.additionalAuthorizationParameters },\n requireIssuerParameter: options.requireIssuerParameter ?? true,\n callbackPath: options.callbackPath ?? AuthioBffDefaults.CallbackPath,\n signedOutCallbackPath: options.signedOutCallbackPath ?? AuthioBffDefaults.SignedOutCallbackPath,\n defaultReturnUrl: options.defaultReturnUrl ?? \"/\",\n cookieName: options.cookieName ?? AuthioBffDefaults.CookieName,\n cookieSameSite: options.cookieSameSite ?? \"lax\",\n sessionLifetimeMs: (options.sessionLifetime ?? AuthioBffDefaults.SessionLifetime) * 1000,\n slidingExpiration: options.slidingExpiration ?? true,\n sessionValidation: options.sessionValidation ?? \"introspection\",\n sessionValidationIntervalMs: (options.sessionValidationInterval ?? AuthioBffDefaults.SessionValidationInterval) * 1000,\n revokeRefreshTokenOnLogout: options.revokeRefreshTokenOnLogout ?? true,\n antiForgeryHeaderName: options.antiForgeryHeaderName ?? AuthioBffDefaults.AntiForgeryHeaderName,\n antiForgeryHeaderValue: options.antiForgeryHeaderValue ?? AuthioBffDefaults.AntiForgeryHeaderValue,\n sessionKeyPrefix: options.sessionKeyPrefix ?? AuthioBffDefaults.SessionKeyPrefix,\n backChannelLogout: options.backChannelLogout ?? true,\n frontChannelLogout: options.frontChannelLogout ?? false,\n tokenRefreshSkewMs: (options.tokenRefreshSkew ?? 60) * 1000,\n redirectUri: nonEmpty(options.redirectUri),\n postLogoutRedirectUri: nonEmpty(options.postLogoutRedirectUri),\n onError: options.onError ?? (() => undefined),\n };\n\n if (cookieSecrets.length === 0) problems.push(\"cookieSecret is required: the session cookie is signed with it.\");\n else if (cookieSecrets.some((secret) => secret.length < 32)) problems.push(\"Every cookieSecret must be at least 32 characters long.\");\n\n if (!settings.cookieName.trim()) problems.push(\"cookieName is required.\");\n else if (!settings.cookieName.startsWith(\"__Host-\") && !settings.cookieName.startsWith(\"__Secure-\"))\n problems.push(\"cookieName must start with __Host- (or __Secure-) so browsers enforce a Secure, host-only cookie.\");\n else if (!/^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/.test(settings.cookieName)) problems.push(\"cookieName holds characters a cookie name cannot.\");\n\n if (settings.cookieSameSite !== \"lax\" && settings.cookieSameSite !== \"strict\") problems.push(\"cookieSameSite must be lax or strict.\");\n if (!isPositive(settings.sessionLifetimeMs)) problems.push(\"sessionLifetime must be a positive number of seconds.\");\n\n if (settings.sessionValidation !== \"none\" && settings.sessionValidation !== \"introspection\")\n problems.push(\"sessionValidation must be none or introspection.\");\n else if (settings.sessionValidation === \"introspection\" && !isPositive(settings.sessionValidationIntervalMs))\n problems.push(\"sessionValidationInterval must be a positive number of seconds.\");\n\n if (!settings.antiForgeryHeaderName.trim() || !/^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/.test(settings.antiForgeryHeaderName))\n problems.push(\"antiForgeryHeaderName must be a header name.\");\n if (!settings.antiForgeryHeaderValue) problems.push(\"antiForgeryHeaderValue is required.\");\n if (!isLocalUrl(settings.defaultReturnUrl)) problems.push(\"defaultReturnUrl must be a local URL starting with a single '/'.\");\n if (!isLocalUrl(settings.callbackPath)) problems.push(\"callbackPath must start with '/'.\");\n if (!isLocalUrl(settings.signedOutCallbackPath)) problems.push(\"signedOutCallbackPath must start with '/'.\");\n if (settings.endpointPrefix === \"/\") problems.push(\"endpointPrefix cannot be empty.\");\n if (settings.prompt !== undefined && !AuthioPrompts.includes(settings.prompt)) problems.push(\"prompt must be none, login, select_account or consent.\");\n\n if (settings.maxAge !== undefined && (!Number.isInteger(settings.maxAge) || settings.maxAge < 0))\n problems.push(\"maxAge must be a non-negative whole number of seconds.\");\n\n if (!settings.sessionKeyPrefix.trim()) problems.push(\"sessionKeyPrefix is required.\");\n if (options.responseMode !== undefined && options.responseMode !== \"query\")\n problems.push(\"responseMode must be query: the BFF reads Authio's answer at callbackPath (web_message needs a page of the SPA's own).\");\n if (!Number.isFinite(settings.tokenRefreshSkewMs) || settings.tokenRefreshSkewMs < 0) problems.push(\"tokenRefreshSkew must be a non-negative number of seconds.\");\n\n if (problems.length > 0) throw new AuthioConfigurationError(`The Authio BFF options are not valid:\\n- ${problems.join(\"\\n- \")}`);\n\n return settings;\n}\n\n/**\n * Whether a URL is local to the application: it starts with a single `/` (not `//` nor `/\\`) and holds no control\n * characters, so redirecting to it cannot leave the site.\n */\nexport function isLocalUrl(url: string | undefined | null): url is string {\n if (typeof url !== \"string\" || !url || /[\\u0000-\\u001f\\u007f-\\u009f]/.test(url)) return false;\n\n return url[0] === \"/\" && (url.length === 1 || (url[1] !== \"/\" && url[1] !== \"\\\\\"));\n}\n\nfunction distinct(scopes: readonly string[]): readonly string[] {\n return Object.freeze([...new Set(scopes.map((scope) => scope.trim()).filter(Boolean))]);\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n return value?.trim() ? value : undefined;\n}\n\nfunction isPositive(value: number): boolean {\n return Number.isFinite(value) && value > 0;\n}\n","import { createCipheriv, createDecipheriv, createHmac, hkdfSync, randomBytes, timingSafeEqual } from \"node:crypto\";\n\n/**\n * What the BFF signs or encrypts, each with its own key derived from `cookieSecret`.\n *\n * @internal\n */\nexport type AuthioBffProtectionPurpose = \"session-cookie\" | \"session-data\" | \"login\" | \"logout-state\";\n\n/**\n * Signs and encrypts with keys derived (HKDF-SHA256) from the cookie secrets: the first secret protects, every one is\n * accepted when reading.\n *\n * @internal\n */\nexport interface AuthioBffProtector {\n /** `value.signature`, HMAC-SHA256. */\n sign(value: string): string;\n /** The value of a signed text, or `undefined` when no secret's signature matches. */\n unsign(signed: string): string | undefined;\n /** AES-256-GCM over the JSON of `value`, base64url. */\n seal(purpose: AuthioBffProtectionPurpose, value: unknown): string;\n /** The value sealed for `purpose`, or `undefined` when it cannot be opened. */\n open<T>(purpose: AuthioBffProtectionPurpose, sealed: string): T | undefined;\n}\n\n/**\n * Creates the protector.\n *\n * @internal\n */\nexport function createAuthioBffProtector(secrets: readonly string[]): AuthioBffProtector {\n const keys = new Map<AuthioBffProtectionPurpose, Buffer[]>();\n const keysFor = (purpose: AuthioBffProtectionPurpose) => {\n let derived = keys.get(purpose);\n\n if (!derived) {\n derived = secrets.map((secret) => Buffer.from(hkdfSync(\"sha256\", secret, \"authio-bff\", `authio-bff:${purpose}`, 32)));\n keys.set(purpose, derived);\n }\n\n return derived;\n };\n const mac = (key: Buffer, value: string) => createHmac(\"sha256\", key).update(value, \"utf8\").digest();\n\n return {\n sign(value) {\n return `${value}.${mac(keysFor(\"session-cookie\")[0]!, value).toString(\"base64url\")}`;\n },\n unsign(signed) {\n const dot = signed.lastIndexOf(\".\");\n\n if (dot <= 0) return undefined;\n\n const value = signed.slice(0, dot);\n const signature = Buffer.from(signed.slice(dot + 1), \"base64url\");\n\n for (const key of keysFor(\"session-cookie\")) {\n const expected = mac(key, value);\n\n if (signature.length === expected.length && timingSafeEqual(signature, expected)) return value;\n }\n\n return undefined;\n },\n seal(purpose, value) {\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", keysFor(purpose)[0]!, iv);\n const ciphertext = Buffer.concat([cipher.update(JSON.stringify(value), \"utf8\"), cipher.final()]);\n\n return Buffer.concat([iv, ciphertext, cipher.getAuthTag()]).toString(\"base64url\");\n },\n open<T>(purpose: AuthioBffProtectionPurpose, sealed: string) {\n const bytes = Buffer.from(sealed, \"base64url\");\n\n if (bytes.length < 29) return undefined;\n\n for (const key of keysFor(purpose)) {\n try {\n const decipher = createDecipheriv(\"aes-256-gcm\", key, bytes.subarray(0, 12));\n\n decipher.setAuthTag(bytes.subarray(bytes.length - 16));\n\n const plaintext = Buffer.concat([decipher.update(bytes.subarray(12, bytes.length - 16)), decipher.final()]).toString(\"utf8\");\n\n return JSON.parse(plaintext) as T;\n } catch {\n continue;\n }\n }\n\n return undefined;\n },\n };\n}\n","import { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport type { Request, Response } from \"express\";\nimport { AuthioConfigurationError } from \"@hyper.authio/client\";\nimport { sendError } from \"./http.js\";\n\n/**\n * Which token a remote API call is forwarded with, as `AuthioBffRemoteApiTokenMode` in .NET:\n *\n * - `user`: the person's access token (refreshed when needed); anonymous calls are refused with `401`.\n * - `userOrNone`: the person's token when signed in, otherwise no token.\n * - `clientCredentials`: a client-credentials token of the BFF itself, whoever is signed in.\n * - `userOrClientCredentials`: the person's token when signed in, otherwise a client-credentials token.\n * - `none`: no token (cookies and the anti-forgery header are still stripped).\n */\nexport type AuthioBffRemoteApiTokenMode = \"user\" | \"userOrNone\" | \"clientCredentials\" | \"userOrClientCredentials\" | \"none\";\n\n/**\n * Settings of one remote API.\n */\nexport interface AuthioBffRemoteApiOptions {\n /** Which token the calls are forwarded with. Defaults to `user`. */\n tokenMode?: AuthioBffRemoteApiTokenMode;\n /**\n * The resource (RFC 8707) the token must be issued for: a user token is exchanged for it (cached per session and\n * resource), a client-credentials token is asked for it.\n */\n resource?: string;\n /** The scopes the token must carry; for a user token, setting them triggers a token exchange (down-scoping). */\n scopes?: readonly string[];\n /** Requires the anti-forgery header on every call. Defaults to `true`; turn it off only for an anonymous API. */\n requireAntiForgery?: boolean;\n /** When the remote API answers `401` to a user call, checks the Authio session and ends the BFF session if it is gone. Defaults to `true`. */\n validateSessionOnUnauthorized?: boolean;\n /** The `fetch` the calls go through. Defaults to the global one. */\n fetch?: typeof fetch;\n}\n\n/**\n * A remote API, resolved.\n *\n * @internal\n */\nexport interface AuthioBffRemoteApi {\n readonly destination: string;\n readonly tokenMode: AuthioBffRemoteApiTokenMode;\n readonly resource: string | undefined;\n readonly scopes: readonly string[];\n readonly requireAntiForgery: boolean;\n readonly validateSessionOnUnauthorized: boolean;\n readonly fetch: typeof fetch;\n}\n\n/**\n * What forwarding needs from the BFF.\n *\n * @internal\n */\nexport interface AuthioBffRemoteApiContext {\n antiForgery(): boolean;\n readonly antiForgeryHeaderName: string;\n hasSession(): Promise<boolean>;\n userToken(): Promise<string | undefined>;\n clientToken(): Promise<string>;\n endIfInactive(): Promise<void>;\n}\n\nconst tokenModes: readonly AuthioBffRemoteApiTokenMode[] = [\"user\", \"userOrNone\", \"clientCredentials\", \"userOrClientCredentials\", \"none\"];\n\nconst hopByHop = new Set([\"connection\", \"keep-alive\", \"proxy-authenticate\", \"proxy-authorization\", \"proxy-connection\", \"te\", \"trailer\", \"transfer-encoding\", \"upgrade\"]);\n\nconst decodedEncodings = new Set([\"gzip\", \"x-gzip\", \"deflate\", \"br\"]);\n\n/**\n * Resolves and validates a remote API's settings.\n *\n * @throws AuthioConfigurationError when the destination is not an absolute HTTP(S) URL or the token mode is unknown.\n * @internal\n */\nexport function resolveRemoteApi(destination: string, options: AuthioBffRemoteApiOptions): AuthioBffRemoteApi {\n let url: URL;\n\n try {\n url = new URL(destination);\n } catch {\n throw new AuthioConfigurationError(`The remote API destination '${destination}' must be an absolute HTTP(S) URL.`);\n }\n\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\")\n throw new AuthioConfigurationError(`The remote API destination '${destination}' must be an absolute HTTP(S) URL.`);\n\n const tokenMode = options.tokenMode ?? \"user\";\n\n if (!tokenModes.includes(tokenMode)) throw new AuthioConfigurationError(`The remote API tokenMode must be one of ${tokenModes.join(\", \")}.`);\n\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n\n if (typeof fetchImplementation !== \"function\") throw new AuthioConfigurationError(\"No fetch implementation is available: pass fetch to remoteApi.\");\n\n return {\n destination: destination.replace(/\\/+$/, \"\"),\n tokenMode,\n resource: options.resource?.trim() || undefined,\n scopes: [...(options.scopes ?? [])],\n requireAntiForgery: options.requireAntiForgery ?? true,\n validateSessionOnUnauthorized: options.validateSessionOnUnauthorized ?? true,\n fetch: fetchImplementation,\n };\n}\n\n/**\n * Forwards one call: enforces the anti-forgery header, obtains the token, maps the path below the mount point onto\n * the destination, strips the browser's cookies, the anti-forgery header and any `Authorization`, drops upstream\n * `Set-Cookie`, and after an upstream `401` to a user call checks the Authio session. An unreachable API answers `502`.\n *\n * @internal\n */\nexport async function forwardToRemoteApi(request: Request, response: Response, remote: AuthioBffRemoteApi, context: AuthioBffRemoteApiContext): Promise<void> {\n if (remote.requireAntiForgery && !context.antiForgery())\n return sendError(response, 401, \"antiforgery_required\", `The ${context.antiForgeryHeaderName} header is required.`);\n\n const token = await tokenFor(remote, context);\n\n if (token.refused) return sendError(response, 401, \"unauthorized\", \"Sign in first.\");\n\n const headers = outgoingHeaders(request, context.antiForgeryHeaderName);\n\n if (token.accessToken) headers.set(\"authorization\", `Bearer ${token.accessToken}`);\n\n let upstream: globalThis.Response;\n\n try {\n upstream = await remote.fetch(remote.destination + remainingUrl(request), {\n method: request.method,\n headers,\n body: outgoingBody(request),\n redirect: \"manual\",\n duplex: \"half\",\n } as RequestInit);\n } catch {\n return sendError(response, 502, \"bad_gateway\", \"The remote API could not be reached.\");\n }\n\n if (upstream.status === 401 && token.isUserToken && remote.validateSessionOnUnauthorized) await context.endIfInactive();\n\n if (response.headersSent) return;\n\n const encoding = upstream.headers.get(\"content-encoding\")?.trim().toLowerCase();\n const decoded = encoding !== undefined && decodedEncodings.has(encoding);\n\n response.status(upstream.status);\n\n upstream.headers.forEach((value, name) => {\n if (hopByHop.has(name) || name === \"set-cookie\" || (decoded && (name === \"content-encoding\" || name === \"content-length\"))) return;\n\n response.setHeader(name, value);\n });\n\n if (!upstream.body || request.method === \"HEAD\") {\n response.end();\n return;\n }\n\n await pipeline(Readable.fromWeb(upstream.body as NodeReadableStream), response);\n}\n\nasync function tokenFor(remote: AuthioBffRemoteApi, context: AuthioBffRemoteApiContext): Promise<{ refused: boolean; accessToken?: string; isUserToken?: boolean }> {\n switch (remote.tokenMode) {\n case \"none\":\n return { refused: false };\n case \"clientCredentials\":\n return { refused: false, accessToken: await context.clientToken() };\n default: {\n const userToken = (await context.hasSession()) ? await context.userToken() : undefined;\n\n if (userToken) return { refused: false, accessToken: userToken, isUserToken: true };\n if (remote.tokenMode === \"userOrNone\") return { refused: false };\n if (remote.tokenMode === \"userOrClientCredentials\") return { refused: false, accessToken: await context.clientToken() };\n\n return { refused: true };\n }\n }\n}\n\nfunction outgoingHeaders(request: Request, antiForgeryHeaderName: string): Headers {\n const headers = new Headers();\n const skipped = new Set([\n ...hopByHop,\n \"host\",\n \"cookie\",\n \"authorization\",\n \"content-length\",\n antiForgeryHeaderName.toLowerCase(),\n ...(request.headers.connection ?? \"\").split(\",\").map((name) => name.trim().toLowerCase()),\n ]);\n\n for (const [name, value] of Object.entries(request.headers)) {\n if (value === undefined || skipped.has(name)) continue;\n\n for (const item of Array.isArray(value) ? value : [value]) headers.append(name, item);\n }\n\n headers.set(\"accept-encoding\", \"identity\");\n\n return headers;\n}\n\nfunction outgoingBody(request: Request): BodyInit | undefined {\n const declaresBody = request.headers[\"transfer-encoding\"] !== undefined || Number(request.headers[\"content-length\"] ?? 0) > 0;\n\n if (request.method === \"GET\" || request.method === \"HEAD\" || !declaresBody) return undefined;\n\n const parsed = (request as Request & { body?: unknown }).body;\n\n if (!request.readableEnded) return Readable.toWeb(request) as unknown as BodyInit;\n if (parsed === undefined || parsed === null) return undefined;\n if (Buffer.isBuffer(parsed)) return new Uint8Array(parsed);\n if (typeof parsed === \"string\") return parsed;\n if ((request.headers[\"content-type\"] ?? \"\").toLowerCase().startsWith(\"application/x-www-form-urlencoded\"))\n return new URLSearchParams(parsed as Record<string, string>).toString();\n\n return JSON.stringify(parsed);\n}\n\nfunction remainingUrl(request: Request): string {\n const url = request.url || \"/\";\n const originalPath = new URL(request.originalUrl || url, \"http://localhost\").pathname;\n\n if ((url === \"/\" || url.startsWith(\"/?\")) && !originalPath.endsWith(\"/\")) return url.slice(1);\n\n return url;\n}\n","/**\n * Hands out one asynchronous lock per session, so concurrent requests of the same person never refresh the same\n * refresh token twice (Authio rotates it and treats a late reuse as a replay that revokes the session). The lock is\n * local to the process, as `AuthioBffSessionLockProvider` is in .NET: with several instances, keep a person on one\n * instance or rely on Authio's short reuse leeway.\n *\n * @internal\n */\nexport class AuthioBffSessionLocks {\n private readonly tails = new Map<string, { promise: Promise<void>; references: number }>();\n\n /** The number of keys with a holder or a waiter. */\n get size(): number {\n return this.tails.size;\n }\n\n /**\n * Runs `work` once every earlier holder of `key` released it, and releases it afterwards, even when `work` throws.\n */\n async run<T>(key: string, work: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n let release!: () => void;\n const turn = new Promise<void>((resolve) => {\n release = resolve;\n });\n const entry = { promise: (previous?.promise ?? Promise.resolve()).then(() => turn), references: (previous?.references ?? 0) + 1 };\n\n this.tails.set(key, entry);\n\n try {\n await previous?.promise;\n\n return await work();\n } finally {\n release();\n\n const current = this.tails.get(key);\n\n if (current) {\n current.references -= 1;\n if (current.references === 0) this.tails.delete(key);\n }\n }\n }\n}\n","import { systemClock, type AuthioClock } from \"@hyper.authio/client\";\n\n/**\n * A session as the store keeps it. `data` is encrypted by the BFF (AES-256-GCM, from `cookieSecret`): the store never\n * sees the tokens. `sessionId` and `subject` are kept in clear so back-channel logout can find the sessions to end.\n */\nexport interface AuthioBffStoredSession {\n /** The store key: `sessionKeyPrefix` followed by 64 random hex characters. The cookie carries the part after the prefix. */\n readonly key: string;\n /** The Authio session (`sid` of the ID token), when Authio named one. */\n readonly sessionId: string | undefined;\n /** The person (`sub`). */\n readonly subject: string | undefined;\n /** When the session expires, in milliseconds since the epoch; a store may drop it from then on. */\n readonly expiresAt: number;\n /** The encrypted session. */\n readonly data: string;\n}\n\n/**\n * Where the BFF keeps its sessions. The default is in memory (one process); implement this over Redis or a database for\n * several instances, indexing each session by `sessionId` and `subject` so back-channel logout can end them.\n * Every method may return a value or a promise.\n */\nexport interface AuthioBffSessionStore {\n /** Reads a session; `undefined` when it is unknown or expired. */\n get(key: string): AuthioBffStoredSession | undefined | Promise<AuthioBffStoredSession | undefined>;\n /** Creates or replaces a session, kept until `expiresAt`. */\n set(session: AuthioBffStoredSession): void | Promise<void>;\n /** Deletes a session. */\n delete(key: string): void | Promise<void>;\n /** Deletes every session of an Authio session (`sid`). */\n deleteBySessionId(sessionId: string): void | Promise<void>;\n /** Deletes every session of a person (`sub`). */\n deleteBySubject(subject: string): void | Promise<void>;\n}\n\n/**\n * Options of the in-memory store.\n */\nexport interface AuthioBffMemoryStoreOptions {\n /** The clock expiry is measured with. Defaults to the system clock. */\n clock?: AuthioClock;\n}\n\n/**\n * An in-memory session store, indexed by `sessionId` and `subject`, that drops expired sessions. Sessions live in one\n * process and are lost on restart: use a shared store for several instances.\n */\nexport interface AuthioBffMemoryStore extends AuthioBffSessionStore {\n /** The number of sessions held, expired ones included until they are swept. */\n readonly size: number;\n get(key: string): AuthioBffStoredSession | undefined;\n set(session: AuthioBffStoredSession): void;\n delete(key: string): void;\n deleteBySessionId(sessionId: string): void;\n deleteBySubject(subject: string): void;\n}\n\n/**\n * Creates the in-memory session store.\n */\nexport function createAuthioBffMemoryStore(options: AuthioBffMemoryStoreOptions = {}): AuthioBffMemoryStore {\n const clock = options.clock ?? systemClock;\n const sessions = new Map<string, AuthioBffStoredSession>();\n const bySessionId = new Map<string, Set<string>>();\n const bySubject = new Map<string, Set<string>>();\n let nextSweep = 0;\n\n const index = (lookup: Map<string, Set<string>>, value: string | undefined, key: string) => {\n if (!value) return;\n\n const keys = lookup.get(value) ?? new Set<string>();\n\n keys.add(key);\n lookup.set(value, keys);\n };\n\n const unindex = (lookup: Map<string, Set<string>>, value: string | undefined, key: string) => {\n if (!value) return;\n\n const keys = lookup.get(value);\n\n keys?.delete(key);\n if (keys?.size === 0) lookup.delete(value);\n };\n\n const remove = (key: string) => {\n const session = sessions.get(key);\n\n if (!session) return;\n\n sessions.delete(key);\n unindex(bySessionId, session.sessionId, key);\n unindex(bySubject, session.subject, key);\n };\n\n const sweep = () => {\n const now = clock.now();\n\n if (now < nextSweep) return;\n\n nextSweep = now + 60_000;\n\n for (const [key, session] of sessions) if (session.expiresAt <= now) remove(key);\n };\n\n return {\n get size() {\n return sessions.size;\n },\n get(key) {\n const session = sessions.get(key);\n\n if (!session) return undefined;\n if (session.expiresAt > clock.now()) return session;\n\n remove(key);\n\n return undefined;\n },\n set(session) {\n sweep();\n remove(session.key);\n sessions.set(session.key, session);\n index(bySessionId, session.sessionId, session.key);\n index(bySubject, session.subject, session.key);\n },\n delete: remove,\n deleteBySessionId(sessionId) {\n for (const key of [...(bySessionId.get(sessionId) ?? [])]) remove(key);\n },\n deleteBySubject(subject) {\n for (const key of [...(bySubject.get(subject) ?? [])]) remove(key);\n },\n };\n}\n","import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type { NextFunction, Request, RequestHandler, Response } from \"express\";\nimport {\n AuthioDefaults,\n AuthioError,\n AuthioOAuthErrors,\n AuthioPrompts,\n AuthioProtocolError,\n AuthioTokenTypes,\n createAuthioClient,\n type AuthioAuthorizationTransaction,\n type AuthioClient,\n type AuthioClientOptions,\n type AuthioPrompt,\n} from \"@hyper.authio/client\";\nimport { mergeUserInfo, replaceAccessTokenClaims, toAuthioBffClaims, toSessionClaims } from \"./claims.js\";\nimport { hasAntiForgeryHeader, readCookies, readFormField, readQuery, requestBase, sendError, setCookie, withQueryParameter } from \"./http.js\";\nimport { AuthioBffDefaults, isLocalUrl, resolveBffSettings, type AuthioBffOptions } from \"./options.js\";\nimport { createAuthioBffProtector } from \"./protection.js\";\nimport { forwardToRemoteApi, resolveRemoteApi, type AuthioBffRemoteApiOptions } from \"./remote-api.js\";\nimport { AuthioBffSessionLocks } from \"./session-locks.js\";\nimport { createAuthioBffMemoryStore, type AuthioBffSessionStore } from \"./session-store.js\";\n\n/**\n * The signed-in session as the application sees it: who, which Authio session, until when. Never the tokens.\n */\nexport interface AuthioBffSessionInfo {\n /** The person (`sub`). */\n readonly subject: string | undefined;\n /** The Authio session (`sid`). */\n readonly sessionId: string | undefined;\n /** The session's claims: the ID token's, the access token's `*_resource_access` and organization, UserInfo's. */\n readonly claims: Readonly<Record<string, unknown>>;\n /** When the BFF session expires, in milliseconds since the epoch. */\n readonly expiresAt: number;\n}\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n /** The Authio BFF session, once the BFF read it for this request; `undefined` when nobody is signed in. */\n authioBff?: AuthioBffSessionInfo;\n }\n }\n}\n\n/**\n * Options of `bff.api()`.\n */\nexport interface AuthioBffApiOptions {\n /** Requires the anti-forgery header. Defaults to `true`. */\n requireAntiForgery?: boolean;\n /** Lets anonymous calls through (with `req.authioBff` undefined) instead of answering `401`. Defaults to `false`. */\n optional?: boolean;\n}\n\n/**\n * What a user token is asked for: a resource (RFC 8707) and/or narrower scopes make the BFF exchange the session's\n * token (RFC 8693) and cache the result per session, resource and scopes.\n */\nexport interface AuthioBffUserTokenOptions {\n /** The resource the token must be issued for. */\n resource?: string;\n /** The scopes the token must carry. */\n scopes?: readonly string[];\n}\n\n/**\n * The Authio BFF: an Express middleware serving the BFF endpoints, plus the helpers the application's own routes use.\n */\nexport interface AuthioBff extends RequestHandler {\n /** The Authio client the BFF talks to Authio with. */\n readonly client: AuthioClient;\n /** Where the sessions live. */\n readonly store: AuthioBffSessionStore;\n /**\n * Marks a local API: requires the anti-forgery header (`401 antiforgery_required`) and a session (`401\n * unauthorized`), never redirects, and sets `req.authioBff`.\n */\n api(options?: AuthioBffApiOptions): RequestHandler;\n /**\n * Forwards the calls mounted under a path to a remote API with the token `tokenMode` asks for:\n * `app.use(\"/api/orders\", bff.remoteApi(\"https://orders.example.com\"))`. Mount it before any body parser.\n */\n remoteApi(destination: string, options?: AuthioBffRemoteApiOptions): RequestHandler;\n /** Reads the request's session (once per request), checking and renewing it as configured. */\n getSession(request: Request, response: Response): Promise<AuthioBffSessionInfo | undefined>;\n /**\n * The person's access token, refreshed `tokenRefreshSkew` before it expires (one refresh per session at a time), or\n * exchanged for `resource`/`scopes`. `undefined` when nobody is signed in or the session ended (a refused refresh\n * ends it).\n */\n getUserAccessToken(request: Request, response: Response, options?: AuthioBffUserTokenOptions): Promise<string | undefined>;\n /** A `fetch` that sends the person's access token (see `getUserAccessToken`), for calling APIs from a route. */\n userFetch(request: Request, response: Response, options?: AuthioBffUserTokenOptions & { fetch?: typeof fetch }): typeof fetch;\n /** Ends the request's session locally: deletes it from the store and clears the cookie. Authio is not told. */\n endSession(request: Request, response: Response): Promise<void>;\n}\n\ninterface SessionData {\n publicId: string;\n claims: Record<string, unknown>;\n accessToken?: string;\n accessTokenExpiresAt?: number;\n refreshToken?: string;\n idToken?: string;\n tokenType?: string;\n resource?: string;\n createdAt: number;\n validatedAt: number;\n}\n\ninterface LoadedSession {\n readonly key: string;\n readonly expiresAt: number;\n readonly data: SessionData;\n}\n\ninterface LoginState {\n transaction: AuthioAuthorizationTransaction;\n returnUrl: string;\n expiresAt: number;\n}\n\ninterface LoginParameters {\n returnUrl: string;\n prompt?: AuthioPrompt;\n loginHint?: string;\n uiLocales?: string;\n maxAge?: number;\n organization?: string;\n resource?: string;\n}\n\ninterface ExchangedToken {\n readonly sessionKey: string;\n readonly accessToken: string;\n readonly refreshAt: number;\n readonly expiresAt: number;\n}\n\nconst sessionSlot = Symbol.for(\"authio.bff.session\");\n\ntype RequestWithSession = Request & { [sessionSlot]?: Promise<LoadedSession | undefined> };\n\n/**\n * Creates the Authio BFF. Mount it with `app.use(bff)`: it serves `{endpointPrefix}/login`, `/logout`, `/user`,\n * `/silent-login`, `/silent-login-callback`, `/backchannel-logout`, `/frontchannel-logout` (when turned on), the sign-in\n * callback (`callbackPath`) and the sign-out callback (`signedOutCallbackPath`), and reads the session of every other\n * request that carries the cookie.\n *\n * @throws AuthioConfigurationError naming every invalid option.\n */\nexport function authioBff(options: AuthioBffOptions): AuthioBff {\n const settings = resolveBffSettings(options);\n const client = options.client ?? createAuthioClient(options as AuthioClientOptions);\n const clock = client.connection.clock;\n const store = options.store ?? createAuthioBffMemoryStore({ clock });\n const protector = createAuthioBffProtector(settings.cookieSecrets);\n const locks = new AuthioBffSessionLocks();\n const exchanges = new Map<string, ExchangedToken>();\n const prefix = settings.endpointPrefix;\n const loginLifetimeMs = AuthioBffDefaults.LoginLifetime * 1000;\n\n const loginCookieName = (state: string | undefined) =>\n state ? `${settings.cookieName}.login.${createHash(\"sha256\").update(state).digest(\"base64url\").slice(0, 16)}` : `${settings.cookieName}.login`;\n\n const toInfo = (session: LoadedSession): AuthioBffSessionInfo =>\n Object.freeze({\n subject: textOf(session.data.claims.sub),\n sessionId: textOf(session.data.claims.sid),\n claims: Object.freeze({ ...session.data.claims }),\n expiresAt: session.expiresAt,\n });\n\n const expose = (request: Request, session: LoadedSession | undefined) => {\n (request as RequestWithSession)[sessionSlot] = Promise.resolve(session);\n request.authioBff = session ? toInfo(session) : undefined;\n };\n\n const read = async (key: string): Promise<LoadedSession | undefined> => {\n const stored = await store.get(key);\n\n if (!stored || stored.expiresAt <= clock.now()) return undefined;\n\n const data = protector.open<SessionData>(\"session-data\", stored.data);\n\n return data ? { key, expiresAt: stored.expiresAt, data } : undefined;\n };\n\n const write = async (key: string, data: SessionData, expiresAt: number): Promise<LoadedSession> => {\n await store.set({ key, sessionId: textOf(data.claims.sid), subject: textOf(data.claims.sub), expiresAt, data: protector.seal(\"session-data\", data) });\n\n return { key, expiresAt, data };\n };\n\n const update = (key: string, change: (session: LoadedSession) => { data: SessionData; expiresAt: number }) =>\n locks.run(key, async () => {\n const current = await read(key);\n\n if (!current) return undefined;\n\n const next = change(current);\n\n return write(key, next.data, next.expiresAt);\n });\n\n const dropExchanges = (key: string) => {\n for (const [cacheKey, entry] of exchanges) if (entry.sessionKey === key) exchanges.delete(cacheKey);\n };\n\n const clearCookie = (response: Response) => setCookie(response, settings.cookieName, \"\", settings.cookieSameSite, 0);\n\n const endSessionByKey = async (request: Request, response: Response, key: string) => {\n await store.delete(key);\n dropExchanges(key);\n clearCookie(response);\n expose(request, undefined);\n };\n\n const report = (error: unknown) => {\n try {\n settings.onError(error);\n } catch {\n return;\n }\n };\n\n const readAccessToken = async (accessToken: string | undefined): Promise<Record<string, unknown> | undefined> => {\n if (!accessToken) return undefined;\n\n try {\n return await client.readAccessTokenClaims(accessToken);\n } catch (error) {\n report(error);\n\n return undefined;\n }\n };\n\n const refusesIdToken = async (idToken: string, accessToken: string, subject: unknown): Promise<boolean> => {\n try {\n const claims = await client.validateIdToken(idToken, { accessToken });\n\n if (typeof subject === \"string\" && claims.sub !== subject)\n throw new AuthioError(`The ID token of the refresh names '${claims.sub}', not the session's person.`);\n\n return false;\n } catch (error) {\n report(error);\n\n return true;\n }\n };\n\n const isActive = async (data: SessionData): Promise<boolean | undefined> => {\n const token = data.refreshToken ?? data.accessToken;\n\n if (!token) return undefined;\n\n try {\n const result = await client.introspect(token, { tokenTypeHint: data.refreshToken ? AuthioTokenTypes.RefreshToken : AuthioTokenTypes.AccessToken });\n\n return result.active === true;\n } catch (error) {\n report(error);\n\n return undefined;\n }\n };\n\n const maintain = async (request: Request, response: Response, session: LoadedSession): Promise<LoadedSession | undefined> => {\n const now = clock.now();\n const validate = settings.sessionValidation === \"introspection\" && now - session.data.validatedAt >= settings.sessionValidationIntervalMs;\n const slide = settings.slidingExpiration && session.expiresAt - now < settings.sessionLifetimeMs / 2;\n let validated = false;\n\n if (validate) {\n const active = await isActive(session.data);\n\n if (active === false) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n validated = active === true;\n }\n\n if (!validated && !slide) return session;\n\n const renewed = await update(session.key, (current) => ({\n data: validated ? { ...current.data, validatedAt: now } : current.data,\n expiresAt: slide ? now + settings.sessionLifetimeMs : current.expiresAt,\n }));\n\n return renewed;\n };\n\n const loadSession = (request: Request, response: Response): Promise<LoadedSession | undefined> => {\n const holder = request as RequestWithSession;\n const cached = holder[sessionSlot];\n\n if (cached) return cached;\n\n const loading = (async () => {\n const cookie = readCookies(request).get(settings.cookieName);\n\n if (!cookie) return undefined;\n\n const id = protector.unsign(cookie);\n const found = id ? await read(settings.sessionKeyPrefix + id) : undefined;\n const session = found ? await maintain(request, response, found) : undefined;\n\n if (!session) {\n clearCookie(response);\n request.authioBff = undefined;\n return undefined;\n }\n\n request.authioBff = toInfo(session);\n\n return session;\n })();\n\n holder[sessionSlot] = loading;\n\n return loading;\n };\n\n const isFresh = (data: SessionData, skewMs: number) =>\n Boolean(data.accessToken) && (data.accessTokenExpiresAt === undefined || clock.now() < data.accessTokenExpiresAt - skewMs);\n\n const refresh = async (request: Request, response: Response, session: LoadedSession): Promise<string | undefined> => {\n const data = { ...session.data, claims: { ...session.data.claims } };\n const unexpired = isFresh(data, 0) ? data.accessToken : undefined;\n\n if (!data.refreshToken) return unexpired;\n\n try {\n const issuedAt = clock.now();\n const answer = await client.tokens.refresh({ refreshToken: data.refreshToken });\n\n if (answer.id_token && (await refusesIdToken(answer.id_token, answer.access_token, data.claims.sub))) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n data.accessToken = answer.access_token;\n data.accessTokenExpiresAt = issuedAt + lifetimeOf(answer.expires_in);\n data.tokenType = answer.token_type ?? data.tokenType;\n if (answer.refresh_token) data.refreshToken = answer.refresh_token;\n if (answer.id_token) data.idToken = answer.id_token;\n\n replaceAccessTokenClaims(data.claims, await readAccessToken(answer.access_token));\n\n if (!(await store.get(session.key))) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n expose(request, await write(session.key, data, session.expiresAt));\n\n return answer.access_token;\n } catch (error) {\n report(error);\n\n if (error instanceof AuthioProtocolError && error.error === AuthioOAuthErrors.InvalidGrant) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n return unexpired;\n }\n };\n\n const sessionAccessToken = async (request: Request, response: Response): Promise<string | undefined> => {\n const session = await loadSession(request, response);\n\n if (!session) return undefined;\n if (isFresh(session.data, settings.tokenRefreshSkewMs)) return session.data.accessToken;\n\n return locks.run(session.key, async () => {\n const current = await read(session.key);\n\n if (!current) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n if (isFresh(current.data, settings.tokenRefreshSkewMs)) {\n expose(request, current);\n return current.data.accessToken;\n }\n\n return refresh(request, response, current);\n });\n };\n\n const getUserAccessToken: AuthioBff[\"getUserAccessToken\"] = async (request, response, tokenOptions = {}) => {\n const scopes = [...new Set((tokenOptions.scopes ?? []).map((scope) => scope.trim()).filter(Boolean))].sort();\n const resource = tokenOptions.resource?.trim() || undefined;\n const subjectToken = await sessionAccessToken(request, response);\n\n if (!subjectToken || (!resource && scopes.length === 0)) return subjectToken;\n\n const session = await loadSession(request, response);\n\n if (!session) return undefined;\n\n const cacheKey = `${session.key}|${resource ?? \"\"}|${scopes.join(\" \")}`;\n const cached = exchanges.get(cacheKey);\n\n if (cached && clock.now() < cached.refreshAt) return cached.accessToken;\n\n return locks.run(cacheKey, async () => {\n const again = exchanges.get(cacheKey);\n\n if (again && clock.now() < again.refreshAt) return again.accessToken;\n\n const issuedAt = clock.now();\n const answer = await client.tokens.exchange({ subjectToken, scopes: scopes.length > 0 ? scopes : undefined, resource });\n const lifetime = lifetimeOf(answer.expires_in);\n\n for (const [key, entry] of exchanges) if (entry.expiresAt <= issuedAt) exchanges.delete(key);\n\n exchanges.set(cacheKey, {\n sessionKey: session.key,\n accessToken: answer.access_token,\n refreshAt: issuedAt + lifetime - Math.min(settings.tokenRefreshSkewMs, lifetime / 2),\n expiresAt: issuedAt + lifetime,\n });\n\n return answer.access_token;\n });\n };\n\n const endIfInactive = async (request: Request, response: Response) => {\n const session = await loadSession(request, response);\n\n if (session && (await isActive(session.data)) === false) await endSessionByKey(request, response, session.key);\n };\n\n const antiForgery = (request: Request) => hasAntiForgeryHeader(request, settings.antiForgeryHeaderName, settings.antiForgeryHeaderValue);\n\n const antiForgeryRequired = (response: Response) =>\n sendError(response, 401, \"antiforgery_required\", `The ${settings.antiForgeryHeaderName} header is required.`);\n\n const startLogin = async (request: Request, response: Response, parameters: LoginParameters) => {\n const { url, transaction } = await client.createAuthorizationUrl({\n redirectUri: settings.redirectUri ?? requestBase(request) + settings.callbackPath,\n checks: options.checks,\n codeChallengeMethod: options.codeChallengeMethod,\n responseMode: options.responseMode,\n scopes: settings.scopes,\n resource: parameters.resource ?? settings.resource,\n organization: parameters.organization ?? settings.organization,\n prompt: parameters.prompt ?? settings.prompt,\n loginHint: parameters.loginHint,\n uiLocales: parameters.uiLocales ?? settings.uiLocales,\n maxAge: parameters.maxAge ?? settings.maxAge,\n extraParameters: settings.additionalAuthorizationParameters,\n });\n const state: LoginState = { transaction, returnUrl: parameters.returnUrl, expiresAt: clock.now() + loginLifetimeMs };\n\n setCookie(response, loginCookieName(transaction.state), protector.seal(\"login\", state), \"lax\", AuthioBffDefaults.LoginLifetime);\n response.set(\"Cache-Control\", \"no-store\").redirect(302, url);\n };\n\n const login = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const returnUrl = query.get(\"returnUrl\") ?? \"\";\n const prompt = query.get(\"prompt\") ?? \"\";\n const maxAge = query.get(\"max_age\") ?? \"\";\n const resource = query.get(\"resource\") ?? \"\";\n\n if (returnUrl && !isLocalUrl(returnUrl)) return sendError(response, 400, \"invalid_request\", \"returnUrl must be a local URL.\");\n if (prompt && !(AuthioPrompts as readonly string[]).includes(prompt))\n return sendError(response, 400, \"invalid_request\", \"prompt must be none, login, select_account or consent.\");\n if (maxAge && !/^\\d+$/.test(maxAge)) return sendError(response, 400, \"invalid_request\", \"max_age must be a number of seconds.\");\n if (resource && resource !== settings.resource && !settings.allowedResources.includes(resource))\n return sendError(response, 400, \"invalid_target\", \"The resource is not allowed by allowedResources.\");\n\n await startLogin(request, response, {\n returnUrl: returnUrl || settings.defaultReturnUrl,\n prompt: (prompt || undefined) as AuthioPrompt | undefined,\n loginHint: query.get(\"login_hint\") || undefined,\n uiLocales: query.get(\"ui_locales\") || undefined,\n maxAge: maxAge ? Number(maxAge) : undefined,\n organization: query.get(\"organization\") || undefined,\n resource: resource || undefined,\n });\n };\n\n const silentLogin = (request: Request, response: Response) =>\n startLogin(request, response, { returnUrl: `${request.baseUrl ?? \"\"}${prefix}/silent-login-callback`, prompt: \"none\" });\n\n const callback = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const state = query.get(\"state\") || undefined;\n const cookies = readCookies(request);\n const cookieName = [loginCookieName(state), loginCookieName(undefined)].find((name) => cookies.has(name));\n const sealed = cookieName ? cookies.get(cookieName) : undefined;\n const pending = sealed ? protector.open<LoginState>(\"login\", sealed) : undefined;\n\n if (cookieName && sealed) setCookie(response, cookieName, \"\", \"lax\", 0);\n\n response.set(\"Cache-Control\", \"no-store\");\n\n const fail = (target: string, error: string) => response.redirect(302, withQueryParameter(target, \"error\", error));\n\n if (!pending || (pending.transaction?.state !== undefined && pending.transaction.state !== state) || pending.expiresAt <= clock.now())\n return fail(settings.defaultReturnUrl, \"login_failed\");\n\n const target = isLocalUrl(pending.returnUrl) ? pending.returnUrl : settings.defaultReturnUrl;\n\n if (settings.requireIssuerParameter && !query.has(\"iss\") && !query.has(\"error\")) return fail(target, \"login_failed\");\n\n let data: SessionData;\n\n try {\n const { tokens, idToken } = await client.handleAuthorizationCallback(query, pending.transaction);\n const now = clock.now();\n const accessClaims = await readAccessToken(tokens.access_token);\n const claims = toSessionClaims(idToken, textOf(accessClaims?.sub));\n\n replaceAccessTokenClaims(claims, accessClaims);\n\n if (settings.getClaimsFromUserInfoEndpoint) mergeUserInfo(claims, await client.userInfo(tokens.access_token));\n\n data = {\n publicId: randomBytes(16).toString(\"hex\"),\n claims,\n accessToken: tokens.access_token,\n accessTokenExpiresAt: now + lifetimeOf(tokens.expires_in),\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n tokenType: tokens.token_type,\n resource: pending.transaction.resource,\n createdAt: now,\n validatedAt: now,\n };\n } catch (error) {\n report(error);\n\n return fail(target, error instanceof AuthioProtocolError ? error.error : \"login_failed\");\n }\n\n const previous = readCookies(request).get(settings.cookieName);\n const previousId = previous ? protector.unsign(previous) : undefined;\n\n if (previousId) {\n await store.delete(settings.sessionKeyPrefix + previousId);\n dropExchanges(settings.sessionKeyPrefix + previousId);\n }\n\n const id = randomBytes(32).toString(\"hex\");\n\n expose(request, await write(settings.sessionKeyPrefix + id, data, clock.now() + settings.sessionLifetimeMs));\n setCookie(response, settings.cookieName, protector.sign(id), settings.cookieSameSite);\n response.redirect(302, target);\n };\n\n const user = async (request: Request, response: Response) => {\n if (!antiForgery(request)) return antiForgeryRequired(response);\n\n const session = await loadSession(request, response);\n\n if (!session) return sendError(response, 401, \"unauthorized\", \"Nobody is signed in.\");\n\n const expiresIn = Math.max(0, Math.floor((session.expiresAt - clock.now()) / 1000));\n const logoutUrl = `${request.baseUrl ?? \"\"}${prefix}/logout?sid=${encodeURIComponent(session.data.publicId)}`;\n\n response.set(\"Cache-Control\", \"no-store\").json(toAuthioBffClaims(session.data.claims, expiresIn, logoutUrl));\n };\n\n const logout = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const returnUrl = query.get(\"returnUrl\") ?? \"\";\n\n if (returnUrl && !isLocalUrl(returnUrl)) return sendError(response, 400, \"invalid_request\", \"returnUrl must be a local URL.\");\n\n const target = returnUrl || settings.defaultReturnUrl;\n const session = await loadSession(request, response);\n\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!session) {\n clearCookie(response);\n return response.redirect(302, target);\n }\n\n if (!antiForgery(request) && !fixedTimeEquals(query.get(\"sid\") ?? \"\", session.data.publicId))\n return sendError(response, 400, \"invalid_request\", `Logging out requires the ${settings.antiForgeryHeaderName} header or the session's sid parameter.`);\n\n if (settings.revokeRefreshTokenOnLogout && session.data.refreshToken) {\n try {\n await client.revoke(session.data.refreshToken, { tokenTypeHint: AuthioTokenTypes.RefreshToken });\n } catch (error) {\n report(error);\n }\n }\n\n await endSessionByKey(request, response, session.key);\n\n const document = await client.discovery.get();\n\n if (!document.end_session_endpoint) return response.redirect(302, target);\n\n const endSessionUrl = await client.createEndSessionUrl({\n idTokenHint: session.data.idToken,\n postLogoutRedirectUri: settings.postLogoutRedirectUri ?? requestBase(request) + settings.signedOutCallbackPath,\n state: protector.seal(\"logout-state\", { returnUrl: target, expiresAt: clock.now() + loginLifetimeMs }),\n uiLocales: settings.uiLocales,\n });\n\n response.redirect(302, endSessionUrl);\n };\n\n const signedOutCallback = (request: Request, response: Response) => {\n const state = readQuery(request).get(\"state\");\n const value = state ? protector.open<{ returnUrl: string; expiresAt: number }>(\"logout-state\", state) : undefined;\n const target = value && value.expiresAt > clock.now() && isLocalUrl(value.returnUrl) ? value.returnUrl : settings.defaultReturnUrl;\n\n response.set(\"Cache-Control\", \"no-store\").redirect(302, target);\n };\n\n const silentLoginCallback = async (request: Request, response: Response) => {\n const session = await loadSession(request, response);\n const error = readQuery(request).get(\"error\") || null;\n const message = JSON.stringify({ source: AuthioBffDefaults.SilentLoginMessageSource, isLoggedIn: Boolean(session) && !error, error }).replace(\n /[^ -~]|[<>&]/g,\n (character) => `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n response\n .set(\"Cache-Control\", \"no-store\")\n .type(\"text/html; charset=utf-8\")\n .send(\n `<!doctype html><html><head><meta charset=\"utf-8\"><title>Authio</title></head><body><script>(function(){var m=${message};(window.parent!==window?window.parent:window.opener||window).postMessage(m,window.location.origin);})();</script></body></html>`,\n );\n };\n\n const backChannelLogout = async (request: Request, response: Response) => {\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!settings.backChannelLogout) return void response.status(404).end();\n\n const token = await readFormField(request, \"logout_token\");\n\n if (!token?.trim()) return sendError(response, 400, \"invalid_request\", \"The logout_token form field is required.\");\n\n let logout;\n\n try {\n logout = await client.validateLogoutToken(token);\n } catch (error) {\n report(error);\n\n if (!(error instanceof AuthioError)) throw error;\n\n return sendError(response, 400, \"invalid_request\", \"The logout token is not valid.\");\n }\n\n if (logout.sessionId) await store.deleteBySessionId(logout.sessionId);\n else if (logout.subject) await store.deleteBySubject(logout.subject);\n\n response.status(200).end();\n };\n\n const frontChannelLogout = async (request: Request, response: Response) => {\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!settings.frontChannelLogout) return void response.status(404).end();\n\n let sessionId: string | undefined;\n\n try {\n sessionId = client.validateFrontChannelLogout(readQuery(request)).sessionId;\n } catch (error) {\n report(error);\n\n if (!(error instanceof AuthioError)) throw error;\n\n return sendError(response, 400, \"invalid_request\", \"The front-channel logout request is not valid.\");\n }\n\n const cookie = readCookies(request).get(settings.cookieName);\n const id = cookie ? protector.unsign(cookie) : undefined;\n const key = id ? settings.sessionKeyPrefix + id : undefined;\n\n if (sessionId) await store.deleteBySessionId(sessionId);\n else if (key) {\n await store.delete(key);\n dropExchanges(key);\n }\n\n if (key && !(await store.get(key))) clearCookie(response);\n\n response\n .status(200)\n .type(\"text/html; charset=utf-8\")\n .send('<!doctype html><html><head><meta charset=\"utf-8\"><title>Authio</title></head><body></body></html>');\n };\n\n const routes = new Map<string, { methods: readonly string[]; run: (request: Request, response: Response) => unknown }>([\n [settings.callbackPath, { methods: [\"GET\"], run: callback }],\n [settings.signedOutCallbackPath, { methods: [\"GET\"], run: signedOutCallback }],\n [`${prefix}/login`, { methods: [\"GET\"], run: login }],\n [`${prefix}/logout`, { methods: [\"GET\", \"POST\"], run: logout }],\n [`${prefix}/user`, { methods: [\"GET\"], run: user }],\n [`${prefix}/silent-login`, { methods: [\"GET\"], run: silentLogin }],\n [`${prefix}/silent-login-callback`, { methods: [\"GET\"], run: silentLoginCallback }],\n [`${prefix}/backchannel-logout`, { methods: [\"POST\"], run: backChannelLogout }],\n [`${prefix}/frontchannel-logout`, { methods: [\"GET\"], run: frontChannelLogout }],\n ]);\n\n const middleware = (request: Request, response: Response, next: NextFunction) => {\n const route = routes.get(request.path.replace(/(.)\\/+$/, \"$1\"));\n\n if (route && route.methods.includes(request.method)) {\n Promise.resolve()\n .then(() => route.run(request, response))\n .catch(next);\n return;\n }\n\n loadSession(request, response).then(() => next(), next);\n };\n\n const bff = middleware as AuthioBff;\n\n return Object.assign(bff, {\n client,\n store,\n api(apiOptions: AuthioBffApiOptions = {}): RequestHandler {\n return (request, response, next) => {\n if (apiOptions.requireAntiForgery !== false && !antiForgery(request)) return antiForgeryRequired(response);\n\n loadSession(request, response).then((session) => {\n if (!session && !apiOptions.optional) return sendError(response, 401, \"unauthorized\", \"Sign in first.\");\n\n next();\n }, next);\n };\n },\n remoteApi(destination: string, remoteOptions: AuthioBffRemoteApiOptions = {}): RequestHandler {\n const remote = resolveRemoteApi(destination, remoteOptions);\n\n return (request, response, next) => {\n forwardToRemoteApi(request, response, remote, {\n antiForgery: () => antiForgery(request),\n antiForgeryHeaderName: settings.antiForgeryHeaderName,\n hasSession: async () => Boolean(await loadSession(request, response)),\n userToken: () => getUserAccessToken(request, response, { resource: remote.resource, scopes: remote.scopes }),\n clientToken: async () => (await client.clientCredentials.getToken({ scopes: remote.scopes, resource: remote.resource })).accessToken,\n endIfInactive: () => endIfInactive(request, response),\n }).catch(next);\n };\n },\n async getSession(request: Request, response: Response) {\n const session = await loadSession(request, response);\n\n return session ? toInfo(session) : undefined;\n },\n getUserAccessToken,\n userFetch(request: Request, response: Response, fetchOptions: AuthioBffUserTokenOptions & { fetch?: typeof fetch } = {}): typeof fetch {\n const inner = fetchOptions.fetch ?? client.connection.fetch;\n\n return async (input, init) => {\n const token = await getUserAccessToken(request, response, fetchOptions);\n const headers = new Headers(init?.headers ?? (input instanceof globalThis.Request ? input.headers : undefined));\n\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n\n return inner(input, { ...init, headers });\n };\n },\n async endSession(request: Request, response: Response) {\n const session = await loadSession(request, response);\n\n if (session) await endSessionByKey(request, response, session.key);\n },\n });\n}\n\nfunction lifetimeOf(expiresIn: number | undefined): number {\n return (expiresIn && expiresIn > 0 ? expiresIn : AuthioDefaults.AssumedTokenLifetime) * 1000;\n}\n\nfunction textOf(value: unknown): string | undefined {\n return typeof value === \"string\" && value ? value : undefined;\n}\n\nfunction fixedTimeEquals(left: string, right: string): boolean {\n const a = Buffer.from(left, \"utf8\");\n const b = Buffer.from(right, \"utf8\");\n\n return a.length > 0 && a.length === b.length && timingSafeEqual(a, b);\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/claims.ts","../src/http.ts","../src/options.ts","../src/protection.ts","../src/remote-api.ts","../src/session-locks.ts","../src/session-store.ts","../src/bff.ts"],"names":["AuthioConfigurationError","AuthioPrompts","target","randomBytes","logout","timingSafeEqual"],"mappings":"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","file":"index.js","sourcesContent":["import { AuthioClaimTypes, AuthioResourceAccessClaims, parseResourceAccess, resourceAccessSourceOf } from \"@hyper.authio/client\";\n\n/**\n * The claim types `/bff/user` adds to the person's claims.\n */\nexport const AuthioBffClaimTypes = {\n /** Seconds until the BFF session expires. */\n SessionExpiresIn: \"bff:session_expires_in\",\n /** The URL the SPA navigates to in order to log out; it carries the session's `sid`. */\n LogoutUrl: \"bff:logout_url\",\n /** One Authio role the person holds (flattened from the `*_resource_access` claims). */\n Role: \"role\",\n /** One permission the person holds, as `{resource}:{method}` (flattened from the `*_resource_access` claims). */\n Permission: \"permission\",\n} as const;\n\n/**\n * One entry of the `/bff/user` answer: a string value, or a number for `bff:session_expires_in`.\n */\nexport interface AuthioBffClaim {\n readonly type: string;\n readonly value: string | number;\n}\n\n/**\n * The JSON body of a BFF refusal, shaped like an OAuth error.\n */\nexport interface AuthioBffError {\n readonly error: string;\n readonly error_description?: string;\n}\n\nconst accessTokenClaimTypes = new Set<string>([\n ...Object.keys(AuthioResourceAccessClaims),\n AuthioClaimTypes.OrganizationId,\n AuthioClaimTypes.OrganizationAlias,\n AuthioClaimTypes.AccountId,\n]);\n\nconst protocolClaimTypes = new Set([\"nonce\", \"aud\", \"azp\", \"iss\", \"iat\", \"nbf\", \"exp\", \"at_hash\", \"c_hash\", \"ipaddr\", \"platf\", \"ver\"]);\n\n/**\n * The session's claims from a validated ID token: every claim except the protocol ones the OpenID Connect handler of\n * ASP.NET Core drops (`nonce`, `aud`, `azp`, `iss`, `iat`, `nbf`, `exp`, `at_hash`…).\n *\n * @internal\n */\nexport function toSessionClaims(idToken: Readonly<Record<string, unknown>> | undefined, fallbackSubject: string | undefined): Record<string, unknown> {\n const claims: Record<string, unknown> = {};\n\n for (const [type, value] of Object.entries(idToken ?? {})) if (!protocolClaimTypes.has(type) && value !== undefined && value !== null) claims[type] = value;\n\n if (claims.sub === undefined && fallbackSubject) claims.sub = fallbackSubject;\n\n return claims;\n}\n\n/**\n * Adds the UserInfo claims the session does not carry yet.\n *\n * @internal\n */\nexport function mergeUserInfo(claims: Record<string, unknown>, userInfo: Readonly<Record<string, unknown>>): void {\n for (const [type, value] of Object.entries(userInfo)) if (claims[type] === undefined && value !== undefined && value !== null) claims[type] = value;\n}\n\n/**\n * Replaces the claims only the access token carries (the seven `*_resource_access`, `org_id`, `org_alias`,\n * `account_id`) with those of the access token's verified payload (`AuthioClient.readAccessTokenClaims`) or of its\n * introspection answer. Without either (a token the BFF cannot open or verify, a failed introspection on a refresh)\n * nothing changes.\n *\n * @internal\n */\nexport function replaceAccessTokenClaims(claims: Record<string, unknown>, payload: Readonly<Record<string, unknown>> | undefined): void {\n if (!payload) return;\n\n for (const type of Object.keys(claims)) if (accessTokenClaimTypes.has(type)) delete claims[type];\n for (const [type, value] of Object.entries(payload)) if (accessTokenClaimTypes.has(type) && value !== undefined && value !== null) claims[type] = value;\n}\n\n/**\n * Builds the `/bff/user` answer: every claim of the session but the raw `*_resource_access` JSON (arrays as one entry\n * per element, other values as text), then one `role` per Authio role and one `permission` per grant, then\n * `bff:session_expires_in` and `bff:logout_url`.\n *\n * @internal\n */\nexport function toAuthioBffClaims(claims: Readonly<Record<string, unknown>>, sessionExpiresIn: number, logoutUrl: string): AuthioBffClaim[] {\n const entries: AuthioBffClaim[] = [];\n const seen = new Set<string>();\n const add = (type: string, value: string) => {\n const key = `${type}\\u0000${value}`;\n\n if (seen.has(key)) return;\n\n seen.add(key);\n entries.push({ type, value });\n };\n\n for (const [type, value] of Object.entries(claims)) {\n if (resourceAccessSourceOf(type)) continue;\n\n for (const item of Array.isArray(value) ? value : [value]) if (item !== undefined && item !== null) add(type, toText(item));\n }\n\n const access = parseResourceAccess(claims);\n\n for (const role of access.roles) add(AuthioBffClaimTypes.Role, role);\n for (const [resource, methods] of Object.entries(access.permissions)) for (const method of methods) add(AuthioBffClaimTypes.Permission, `${resource}:${method}`);\n\n entries.push({ type: AuthioBffClaimTypes.SessionExpiresIn, value: sessionExpiresIn });\n entries.push({ type: AuthioBffClaimTypes.LogoutUrl, value: logoutUrl });\n\n return entries;\n}\n\nfunction toText(value: unknown): string {\n return typeof value === \"string\" ? value : typeof value === \"object\" ? JSON.stringify(value) : String(value);\n}\n","import type { Request, Response } from \"express\";\nimport type { AuthioBffCookieSameSite } from \"./options.js\";\n\n/**\n * Reads the request's cookies, first value per name, without needing `cookie-parser`.\n *\n * @internal\n */\nexport function readCookies(request: Request): Map<string, string> {\n const cookies = new Map<string, string>();\n\n for (const part of (request.headers.cookie ?? \"\").split(\";\")) {\n const separator = part.indexOf(\"=\");\n\n if (separator <= 0) continue;\n\n const name = part.slice(0, separator).trim();\n\n if (!name || cookies.has(name)) continue;\n\n let value = part.slice(separator + 1).trim();\n\n if (value.startsWith('\"') && value.endsWith('\"') && value.length >= 2) value = value.slice(1, -1);\n\n try {\n cookies.set(name, decodeURIComponent(value));\n } catch {\n cookies.set(name, value);\n }\n }\n\n return cookies;\n}\n\n/**\n * Adds a `Set-Cookie` header: `HttpOnly`, `Secure`, `Path=/`, no `Domain`; a session cookie unless `maxAge` (seconds)\n * is given, deleted when it is 0.\n *\n * @internal\n */\nexport function setCookie(response: Response, name: string, value: string, sameSite: AuthioBffCookieSameSite, maxAge?: number): void {\n if (response.headersSent) return;\n\n const attributes = [\n `${name}=${encodeURIComponent(value)}`,\n \"Path=/\",\n ...(maxAge === undefined ? [] : [`Max-Age=${Math.max(0, Math.floor(maxAge))}`]),\n ...(maxAge === 0 ? [\"Expires=Thu, 01 Jan 1970 00:00:00 GMT\"] : []),\n \"HttpOnly\",\n \"Secure\",\n `SameSite=${sameSite === \"strict\" ? \"Strict\" : \"Lax\"}`,\n ];\n\n response.append(\"Set-Cookie\", attributes.join(\"; \"));\n}\n\n/**\n * Answers with a JSON error (`{ error, error_description }`) and `Cache-Control: no-store`, unless the response\n * already started.\n *\n * @internal\n */\nexport function sendError(response: Response, status: number, error: string, description?: string): void {\n if (response.headersSent) return;\n\n response.status(status).set(\"Cache-Control\", \"no-store\").json(description ? { error, error_description: description } : { error });\n}\n\n/**\n * Whether the request carries the anti-forgery header exactly once, with the expected value.\n *\n * @internal\n */\nexport function hasAntiForgeryHeader(request: Request, name: string, value: string): boolean {\n const lower = name.toLowerCase();\n let count = 0;\n let matched = false;\n\n for (let index = 0; index < request.rawHeaders.length; index += 2) {\n if (request.rawHeaders[index]?.toLowerCase() !== lower) continue;\n\n count += 1;\n matched = request.rawHeaders[index + 1] === value;\n }\n\n return count === 1 && matched;\n}\n\n/**\n * The query parameters of the request, first value per name, read from the URL rather than Express's parser.\n *\n * @internal\n */\nexport function readQuery(request: Request): URLSearchParams {\n return new URL(request.originalUrl || request.url, \"http://localhost\").searchParams;\n}\n\n/**\n * The public origin and mount path of the request: `{protocol}://{host}{baseUrl}`. Honours `trust proxy` for the\n * protocol.\n *\n * @internal\n */\nexport function requestBase(request: Request): string {\n return `${request.protocol}://${request.get(\"host\") ?? \"localhost\"}${request.baseUrl ?? \"\"}`;\n}\n\n/**\n * Appends a query parameter to a local URL.\n *\n * @internal\n */\nexport function withQueryParameter(url: string, name: string, value: string): string {\n const hash = url.indexOf(\"#\");\n const base = hash >= 0 ? url.slice(0, hash) : url;\n const fragment = hash >= 0 ? url.slice(hash) : \"\";\n\n return `${base}${base.includes(\"?\") ? \"&\" : \"?\"}${encodeURIComponent(name)}=${encodeURIComponent(value)}${fragment}`;\n}\n\n/**\n * Reads a form field of a urlencoded body, whether a body parser already ran or not.\n *\n * @internal\n */\nexport async function readFormField(request: Request, field: string, maxBytes = 64 * 1024): Promise<string | undefined> {\n const parsed = (request as Request & { body?: unknown }).body;\n\n if (parsed && typeof parsed === \"object\" && !Buffer.isBuffer(parsed)) {\n const value = (parsed as Record<string, unknown>)[field];\n\n if (typeof value === \"string\") return value;\n }\n\n if (!(request.headers[\"content-type\"] ?? \"\").toLowerCase().startsWith(\"application/x-www-form-urlencoded\")) return undefined;\n\n const text = Buffer.isBuffer(parsed) ? parsed.toString(\"utf8\") : typeof parsed === \"string\" ? parsed : request.readableEnded ? undefined : await readText(request, maxBytes);\n\n return text === undefined ? undefined : (new URLSearchParams(text).get(field) ?? undefined);\n}\n\nfunction readText(request: Request, maxBytes: number): Promise<string | undefined> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n let done = false;\n\n request.on(\"data\", (chunk: Buffer) => {\n if (done) return;\n\n size += chunk.byteLength;\n\n if (size > maxBytes) {\n done = true;\n request.pause();\n resolve(undefined);\n return;\n }\n\n chunks.push(chunk);\n });\n request.on(\"end\", () => {\n if (!done) resolve(Buffer.concat(chunks).toString(\"utf8\"));\n });\n request.on(\"error\", reject);\n });\n}\n","import { AuthioConfigurationError, AuthioPrompts, type AuthioClient, type AuthioClientOptions, type AuthioPrompt } from \"@hyper.authio/client\";\nimport type { AuthioBffSessionStore } from \"./session-store.js\";\n\n/**\n * Default names and values of the Authio BFF, the same as `Authio.AspNetCore.Bff`'s.\n */\nexport const AuthioBffDefaults = {\n /** The session cookie name. `__Host-` makes browsers refuse it unless it is `Secure`, has `Path=/` and no `Domain`. */\n CookieName: \"__Host-authio\",\n /** The route prefix of the BFF endpoints. */\n EndpointPrefix: \"/bff\",\n /** The anti-forgery header the SPA sends on every API call. */\n AntiForgeryHeaderName: \"X-CSRF\",\n /** The value the anti-forgery header carries. */\n AntiForgeryHeaderValue: \"1\",\n /** The redirect path Authio sends the person back to after sign-in. */\n CallbackPath: \"/signin-oidc\",\n /** The redirect path Authio sends the person back to after sign-out. */\n SignedOutCallbackPath: \"/signout-callback-oidc\",\n /** The `source` of the message the silent-login page posts to its parent window. */\n SilentLoginMessageSource: \"authio-bff-silent-login\",\n /** The prefix of the keys sessions are stored under. */\n SessionKeyPrefix: \"authio-bff:\",\n /** Seconds a session lasts without activity (8 hours). */\n SessionLifetime: 8 * 60 * 60,\n /** Seconds between two checks of the Authio session (5 minutes). */\n SessionValidationInterval: 5 * 60,\n /** Seconds a sign-in may take between the login request and the callback (15 minutes). */\n LoginLifetime: 15 * 60,\n /** The scopes asked for at sign-in; `offline_access` gives the BFF a refresh token. */\n Scopes: Object.freeze([\"openid\", \"profile\", \"email\", \"offline_access\"]) as readonly string[],\n} as const;\n\n/**\n * How the BFF checks that the person's Authio session is still alive: `none`, or `introspection` of the session's\n * refresh token (its access token when there is none) every `sessionValidationInterval`.\n */\nexport type AuthioBffSessionValidation = \"none\" | \"introspection\";\n\n/**\n * Where the BFF reads the claims only the access token carries (the `*_resource_access` roles and permissions,\n * `org_id`, `org_alias`, `account_id`): `token`, from the access token once its signature verifies; or\n * `introspection`, from Authio's introspection of the access token, asked as the BFF's own client. Mirror the client's\n * access token format: `introspection` for `Lightweight`, whose token leaves those claims to introspection. Under\n * `token`, an opaque (`Reference`) access token is introspected too, and contributes nothing when it is not active to\n * the BFF's client.\n */\nexport type AuthioBffAccessTokenClaims = \"token\" | \"introspection\";\n\n/**\n * The `SameSite` mode of the session cookie.\n */\nexport type AuthioBffCookieSameSite = \"lax\" | \"strict\";\n\n/**\n * Settings of the Authio BFF. The client itself (`issuer` or `authority` + `realm`, `clientId`, `clientSecret`,\n * `tokenEndpointAuthMethod`, `clientPrivateKey`, `clientEncryptionKey`, `checks`, `codeChallengeMethod`,\n * `idTokenSignedResponseAlg`, `tokenRefreshSkew`…) takes the names of `conformance/options.md` and mirrors the client\n * as registered in Authio: an option left out is off. The BFF's own settings are those of `Authio.AspNetCore.Bff`\n * (`Authio:Bff`).\n */\nexport interface AuthioBffOptions extends Partial<AuthioClientOptions> {\n /**\n * An Authio client to use instead of creating one from the connection and credential options above. The BFF still\n * reads `tokenRefreshSkew`, `checks`, `codeChallengeMethod`, `responseMode`, `redirectUri` and\n * `postLogoutRedirectUri` from these options; tokens are validated and decrypted by the client.\n */\n client?: AuthioClient;\n /**\n * Secrets the session cookie is signed with and the stored sessions and sign-in cookies are encrypted with, at least\n * 32 characters each. The first one signs and encrypts; every one is accepted, so a new secret can be put first and\n * the old one removed once the sessions it protects have expired.\n */\n cookieSecret: string | readonly string[];\n /** Where sessions live. Defaults to an in-memory store; give a shared one (Redis…) for several instances. */\n store?: AuthioBffSessionStore;\n /** The route prefix of the BFF endpoints. Defaults to `/bff`. */\n endpointPrefix?: string;\n /**\n * The scopes asked for at sign-in, sent as configured: without `openid` there is no ID token, and the session is\n * built from the access token (and UserInfo). Defaults to `openid profile email offline_access`.\n */\n scopes?: readonly string[];\n /** Adds the `roles` scope, so the session carries the `*_resource_access` claims flattened on `/bff/user`. */\n requestRoles?: boolean;\n /**\n * Where the session's roles, permissions and organization come from, read at sign-in and again on every refresh:\n * `token` (default), the access token once its signature verifies; `introspection`, Authio's introspection of the\n * access token, asked as the BFF's own confidential client. Use `introspection` when the client's access token\n * format is `Lightweight`: then a failed or inactive introspection fails the sign-in, and on a refresh an inactive\n * answer ends the session while any other failure keeps the session's previous claims until the next refresh and\n * goes to `onError`. Under `token`, an opaque (`Reference`) access token is introspected too: an inactive answer\n * (a token requested for another resource server's introspection client) leaves its claims out and keeps the session\n * on a refresh, while a failed introspection fails the sign-in and, on a refresh, keeps the previous claims.\n */\n accessTokenClaims?: AuthioBffAccessTokenClaims;\n /** Calls Authio's UserInfo endpoint after sign-in and adds its claims to the session. Defaults to `false`. */\n getClaimsFromUserInfoEndpoint?: boolean;\n /** The `organization` sent on every sign-in unless the login request names one. */\n organization?: string;\n /**\n * The `resource` (RFC 8707) sent on every sign-in unless the login request names one: the session's access token is\n * then addressed to that API. Keep `offline_access`, so the session check introspects the refresh token.\n */\n resource?: string;\n /** The resources a login request may ask for with `?resource=`; any other is refused with `400`. */\n allowedResources?: readonly string[];\n /** The `prompt` sent on every sign-in unless the login request names one. */\n prompt?: AuthioPrompt;\n /** The `ui_locales` sent on every sign-in and sign-out unless the request names one. */\n uiLocales?: string;\n /** The `max_age` (seconds) sent on every sign-in unless the login request names one. */\n maxAge?: number;\n /** Extra authorize parameters sent on every sign-in. */\n additionalAuthorizationParameters?: Readonly<Record<string, string>>;\n /** Refuses an authorization response without `iss` (RFC 9207). Defaults to `true`; Authio always sends it. */\n requireIssuerParameter?: boolean;\n /** The redirect path registered at Authio for sign-in. Defaults to `/signin-oidc`. */\n callbackPath?: string;\n /** The post-logout redirect path registered at Authio. Defaults to `/signout-callback-oidc`. */\n signedOutCallbackPath?: string;\n /** Where the browser lands after login or logout without a `returnUrl`. Must be local. Defaults to `/`. */\n defaultReturnUrl?: string;\n /** The session cookie name. Defaults to `__Host-authio`; it must start with `__Host-` or `__Secure-`. */\n cookieName?: string;\n /** The session cookie's `SameSite`: `lax` (default) or `strict`. */\n cookieSameSite?: AuthioBffCookieSameSite;\n /** Seconds a session lasts without activity. Defaults to 28800 (8 hours). */\n sessionLifetime?: number;\n /** Renews `sessionLifetime` on activity once half of it has passed. Defaults to `true`. */\n slidingExpiration?: boolean;\n /** How the Authio session is checked. Defaults to `introspection`. */\n sessionValidation?: AuthioBffSessionValidation;\n /** Seconds between two checks of the Authio session. Defaults to 300. */\n sessionValidationInterval?: number;\n /** Revokes the refresh token at Authio on logout. Defaults to `true`. */\n revokeRefreshTokenOnLogout?: boolean;\n /** The anti-forgery header API calls must carry. Defaults to `X-CSRF`. */\n antiForgeryHeaderName?: string;\n /** The value the anti-forgery header must carry. Defaults to `1`. */\n antiForgeryHeaderValue?: string;\n /** The prefix of the keys sessions are stored under. Defaults to `authio-bff:`. */\n sessionKeyPrefix?: string;\n /**\n * Serves `POST {endpointPrefix}/backchannel-logout`, which ends the sessions of the Authio session (`sid`) or person\n * (`sub`) a logout token names. Defaults to `true`; register that URL as the client's back-channel logout URI.\n */\n backChannelLogout?: boolean;\n /**\n * Serves `GET {endpointPrefix}/frontchannel-logout`, which Authio loads in an iframe when a session ends: it ends the\n * sessions of the `sid` it names (with `iss` checked), or the browser's own session when it names none. Defaults to\n * `false`; register that URL as the client's front-channel logout URI, with the session required.\n */\n frontChannelLogout?: boolean;\n /** Called with errors the BFF recovers from: a failed revocation, introspection or refresh, a refused logout token. */\n onError?: (error: unknown) => void;\n}\n\n/**\n * The BFF settings, resolved and validated.\n *\n * @internal\n */\nexport interface AuthioBffSettings {\n readonly cookieSecrets: readonly string[];\n readonly endpointPrefix: string;\n readonly scopes: readonly string[];\n readonly accessTokenClaims: AuthioBffAccessTokenClaims;\n readonly getClaimsFromUserInfoEndpoint: boolean;\n readonly organization: string | undefined;\n readonly resource: string | undefined;\n readonly allowedResources: readonly string[];\n readonly prompt: AuthioPrompt | undefined;\n readonly uiLocales: string | undefined;\n readonly maxAge: number | undefined;\n readonly additionalAuthorizationParameters: Readonly<Record<string, string>>;\n readonly requireIssuerParameter: boolean;\n readonly callbackPath: string;\n readonly signedOutCallbackPath: string;\n readonly defaultReturnUrl: string;\n readonly cookieName: string;\n readonly cookieSameSite: AuthioBffCookieSameSite;\n readonly sessionLifetimeMs: number;\n readonly slidingExpiration: boolean;\n readonly sessionValidation: AuthioBffSessionValidation;\n readonly sessionValidationIntervalMs: number;\n readonly revokeRefreshTokenOnLogout: boolean;\n readonly antiForgeryHeaderName: string;\n readonly antiForgeryHeaderValue: string;\n readonly sessionKeyPrefix: string;\n readonly backChannelLogout: boolean;\n readonly frontChannelLogout: boolean;\n readonly tokenRefreshSkewMs: number;\n readonly redirectUri: string | undefined;\n readonly postLogoutRedirectUri: string | undefined;\n readonly onError: (error: unknown) => void;\n}\n\n/**\n * Resolves the BFF settings, naming every problem at once.\n *\n * @throws AuthioConfigurationError listing what is wrong.\n * @internal\n */\nexport function resolveBffSettings(options: AuthioBffOptions): AuthioBffSettings {\n const problems: string[] = [];\n const cookieSecrets = (typeof options.cookieSecret === \"string\" ? [options.cookieSecret] : [...(options.cookieSecret ?? [])]).filter(\n (secret) => typeof secret === \"string\",\n );\n const settings: AuthioBffSettings = {\n cookieSecrets,\n endpointPrefix: `/${(options.endpointPrefix ?? AuthioBffDefaults.EndpointPrefix).replace(/^\\/+|\\/+$/g, \"\")}`,\n scopes: distinct([...(options.scopes ?? AuthioBffDefaults.Scopes), ...(options.requestRoles ? [\"roles\"] : [])]),\n accessTokenClaims: options.accessTokenClaims ?? \"token\",\n getClaimsFromUserInfoEndpoint: options.getClaimsFromUserInfoEndpoint ?? false,\n organization: nonEmpty(options.organization),\n resource: nonEmpty(options.resource),\n allowedResources: [...(options.allowedResources ?? [])],\n prompt: options.prompt || undefined,\n uiLocales: nonEmpty(options.uiLocales),\n maxAge: options.maxAge,\n additionalAuthorizationParameters: { ...options.additionalAuthorizationParameters },\n requireIssuerParameter: options.requireIssuerParameter ?? true,\n callbackPath: options.callbackPath ?? AuthioBffDefaults.CallbackPath,\n signedOutCallbackPath: options.signedOutCallbackPath ?? AuthioBffDefaults.SignedOutCallbackPath,\n defaultReturnUrl: options.defaultReturnUrl ?? \"/\",\n cookieName: options.cookieName ?? AuthioBffDefaults.CookieName,\n cookieSameSite: options.cookieSameSite ?? \"lax\",\n sessionLifetimeMs: (options.sessionLifetime ?? AuthioBffDefaults.SessionLifetime) * 1000,\n slidingExpiration: options.slidingExpiration ?? true,\n sessionValidation: options.sessionValidation ?? \"introspection\",\n sessionValidationIntervalMs: (options.sessionValidationInterval ?? AuthioBffDefaults.SessionValidationInterval) * 1000,\n revokeRefreshTokenOnLogout: options.revokeRefreshTokenOnLogout ?? true,\n antiForgeryHeaderName: options.antiForgeryHeaderName ?? AuthioBffDefaults.AntiForgeryHeaderName,\n antiForgeryHeaderValue: options.antiForgeryHeaderValue ?? AuthioBffDefaults.AntiForgeryHeaderValue,\n sessionKeyPrefix: options.sessionKeyPrefix ?? AuthioBffDefaults.SessionKeyPrefix,\n backChannelLogout: options.backChannelLogout ?? true,\n frontChannelLogout: options.frontChannelLogout ?? false,\n tokenRefreshSkewMs: (options.tokenRefreshSkew ?? 60) * 1000,\n redirectUri: nonEmpty(options.redirectUri),\n postLogoutRedirectUri: nonEmpty(options.postLogoutRedirectUri),\n onError: options.onError ?? (() => undefined),\n };\n\n if (cookieSecrets.length === 0) problems.push(\"cookieSecret is required: the session cookie is signed with it.\");\n else if (cookieSecrets.some((secret) => secret.length < 32)) problems.push(\"Every cookieSecret must be at least 32 characters long.\");\n\n if (!settings.cookieName.trim()) problems.push(\"cookieName is required.\");\n else if (!settings.cookieName.startsWith(\"__Host-\") && !settings.cookieName.startsWith(\"__Secure-\"))\n problems.push(\"cookieName must start with __Host- (or __Secure-) so browsers enforce a Secure, host-only cookie.\");\n else if (!/^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/.test(settings.cookieName)) problems.push(\"cookieName holds characters a cookie name cannot.\");\n\n if (settings.cookieSameSite !== \"lax\" && settings.cookieSameSite !== \"strict\") problems.push(\"cookieSameSite must be lax or strict.\");\n if (!isPositive(settings.sessionLifetimeMs)) problems.push(\"sessionLifetime must be a positive number of seconds.\");\n\n if (settings.accessTokenClaims !== \"token\" && settings.accessTokenClaims !== \"introspection\")\n problems.push(\"accessTokenClaims must be token or introspection.\");\n else if (settings.accessTokenClaims === \"introspection\" && !options.client && isPublicClient(options))\n problems.push(\n \"accessTokenClaims introspection needs a confidential client: Authio answers introspection only to a client that authenticates, so set clientSecret or clientPrivateKey.\",\n );\n\n if (settings.sessionValidation !== \"none\" && settings.sessionValidation !== \"introspection\")\n problems.push(\"sessionValidation must be none or introspection.\");\n else if (settings.sessionValidation === \"introspection\" && !isPositive(settings.sessionValidationIntervalMs))\n problems.push(\"sessionValidationInterval must be a positive number of seconds.\");\n\n if (!settings.antiForgeryHeaderName.trim() || !/^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/.test(settings.antiForgeryHeaderName))\n problems.push(\"antiForgeryHeaderName must be a header name.\");\n if (!settings.antiForgeryHeaderValue) problems.push(\"antiForgeryHeaderValue is required.\");\n if (!isLocalUrl(settings.defaultReturnUrl)) problems.push(\"defaultReturnUrl must be a local URL starting with a single '/'.\");\n if (!isLocalUrl(settings.callbackPath)) problems.push(\"callbackPath must start with '/'.\");\n if (!isLocalUrl(settings.signedOutCallbackPath)) problems.push(\"signedOutCallbackPath must start with '/'.\");\n if (settings.endpointPrefix === \"/\") problems.push(\"endpointPrefix cannot be empty.\");\n if (settings.prompt !== undefined && !AuthioPrompts.includes(settings.prompt)) problems.push(\"prompt must be none, login, select_account or consent.\");\n\n if (settings.maxAge !== undefined && (!Number.isInteger(settings.maxAge) || settings.maxAge < 0))\n problems.push(\"maxAge must be a non-negative whole number of seconds.\");\n\n if (!settings.sessionKeyPrefix.trim()) problems.push(\"sessionKeyPrefix is required.\");\n if (options.responseMode !== undefined && options.responseMode !== \"query\")\n problems.push(\"responseMode must be query: the BFF reads Authio's answer at callbackPath (web_message needs a page of the SPA's own).\");\n if (!Number.isFinite(settings.tokenRefreshSkewMs) || settings.tokenRefreshSkewMs < 0) problems.push(\"tokenRefreshSkew must be a non-negative number of seconds.\");\n\n if (problems.length > 0) throw new AuthioConfigurationError(`The Authio BFF options are not valid:\\n- ${problems.join(\"\\n- \")}`);\n\n return settings;\n}\n\n/**\n * Whether a URL is local to the application: it starts with a single `/` (not `//` nor `/\\`) and holds no control\n * characters, so redirecting to it cannot leave the site.\n */\nexport function isLocalUrl(url: string | undefined | null): url is string {\n if (typeof url !== \"string\" || !url || /[\\u0000-\\u001f\\u007f-\\u009f]/.test(url)) return false;\n\n return url[0] === \"/\" && (url.length === 1 || (url[1] !== \"/\" && url[1] !== \"\\\\\"));\n}\n\nfunction isPublicClient(options: AuthioBffOptions): boolean {\n if (options.tokenEndpointAuthMethod !== undefined) return options.tokenEndpointAuthMethod === \"none\";\n\n return !options.clientSecret && options.clientPrivateKey === undefined && !options.clientPrivateKeyPath;\n}\n\nfunction distinct(scopes: readonly string[]): readonly string[] {\n return Object.freeze([...new Set(scopes.map((scope) => scope.trim()).filter(Boolean))]);\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n return value?.trim() ? value : undefined;\n}\n\nfunction isPositive(value: number): boolean {\n return Number.isFinite(value) && value > 0;\n}\n","import { createCipheriv, createDecipheriv, createHmac, hkdfSync, randomBytes, timingSafeEqual } from \"node:crypto\";\n\n/**\n * What the BFF signs or encrypts, each with its own key derived from `cookieSecret`.\n *\n * @internal\n */\nexport type AuthioBffProtectionPurpose = \"session-cookie\" | \"session-data\" | \"login\" | \"logout-state\";\n\n/**\n * Signs and encrypts with keys derived (HKDF-SHA256) from the cookie secrets: the first secret protects, every one is\n * accepted when reading.\n *\n * @internal\n */\nexport interface AuthioBffProtector {\n /** `value.signature`, HMAC-SHA256. */\n sign(value: string): string;\n /** The value of a signed text, or `undefined` when no secret's signature matches. */\n unsign(signed: string): string | undefined;\n /** AES-256-GCM over the JSON of `value`, base64url. */\n seal(purpose: AuthioBffProtectionPurpose, value: unknown): string;\n /** The value sealed for `purpose`, or `undefined` when it cannot be opened. */\n open<T>(purpose: AuthioBffProtectionPurpose, sealed: string): T | undefined;\n}\n\n/**\n * Creates the protector.\n *\n * @internal\n */\nexport function createAuthioBffProtector(secrets: readonly string[]): AuthioBffProtector {\n const keys = new Map<AuthioBffProtectionPurpose, Buffer[]>();\n const keysFor = (purpose: AuthioBffProtectionPurpose) => {\n let derived = keys.get(purpose);\n\n if (!derived) {\n derived = secrets.map((secret) => Buffer.from(hkdfSync(\"sha256\", secret, \"authio-bff\", `authio-bff:${purpose}`, 32)));\n keys.set(purpose, derived);\n }\n\n return derived;\n };\n const mac = (key: Buffer, value: string) => createHmac(\"sha256\", key).update(value, \"utf8\").digest();\n\n return {\n sign(value) {\n return `${value}.${mac(keysFor(\"session-cookie\")[0]!, value).toString(\"base64url\")}`;\n },\n unsign(signed) {\n const dot = signed.lastIndexOf(\".\");\n\n if (dot <= 0) return undefined;\n\n const value = signed.slice(0, dot);\n const signature = Buffer.from(signed.slice(dot + 1), \"base64url\");\n\n for (const key of keysFor(\"session-cookie\")) {\n const expected = mac(key, value);\n\n if (signature.length === expected.length && timingSafeEqual(signature, expected)) return value;\n }\n\n return undefined;\n },\n seal(purpose, value) {\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", keysFor(purpose)[0]!, iv);\n const ciphertext = Buffer.concat([cipher.update(JSON.stringify(value), \"utf8\"), cipher.final()]);\n\n return Buffer.concat([iv, ciphertext, cipher.getAuthTag()]).toString(\"base64url\");\n },\n open<T>(purpose: AuthioBffProtectionPurpose, sealed: string) {\n const bytes = Buffer.from(sealed, \"base64url\");\n\n if (bytes.length < 29) return undefined;\n\n for (const key of keysFor(purpose)) {\n try {\n const decipher = createDecipheriv(\"aes-256-gcm\", key, bytes.subarray(0, 12));\n\n decipher.setAuthTag(bytes.subarray(bytes.length - 16));\n\n const plaintext = Buffer.concat([decipher.update(bytes.subarray(12, bytes.length - 16)), decipher.final()]).toString(\"utf8\");\n\n return JSON.parse(plaintext) as T;\n } catch {\n continue;\n }\n }\n\n return undefined;\n },\n };\n}\n","import { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport type { Request, Response } from \"express\";\nimport { AuthioConfigurationError } from \"@hyper.authio/client\";\nimport { sendError } from \"./http.js\";\n\n/**\n * Which token a remote API call is forwarded with, as `AuthioBffRemoteApiTokenMode` in .NET:\n *\n * - `user`: the person's access token (refreshed when needed); anonymous calls are refused with `401`.\n * - `userOrNone`: the person's token when signed in, otherwise no token.\n * - `clientCredentials`: a client-credentials token of the BFF itself, whoever is signed in.\n * - `userOrClientCredentials`: the person's token when signed in, otherwise a client-credentials token.\n * - `none`: no token (cookies and the anti-forgery header are still stripped).\n */\nexport type AuthioBffRemoteApiTokenMode = \"user\" | \"userOrNone\" | \"clientCredentials\" | \"userOrClientCredentials\" | \"none\";\n\n/**\n * Settings of one remote API.\n */\nexport interface AuthioBffRemoteApiOptions {\n /** Which token the calls are forwarded with. Defaults to `user`. */\n tokenMode?: AuthioBffRemoteApiTokenMode;\n /**\n * The resource (RFC 8707) the token must be issued for: a user token is exchanged for it (cached per session and\n * resource), a client-credentials token is asked for it.\n */\n resource?: string;\n /** The scopes the token must carry; for a user token, setting them triggers a token exchange (down-scoping). */\n scopes?: readonly string[];\n /** Requires the anti-forgery header on every call. Defaults to `true`; turn it off only for an anonymous API. */\n requireAntiForgery?: boolean;\n /** When the remote API answers `401` to a user call, checks the Authio session and ends the BFF session if it is gone. Defaults to `true`. */\n validateSessionOnUnauthorized?: boolean;\n /** The `fetch` the calls go through. Defaults to the global one. */\n fetch?: typeof fetch;\n}\n\n/**\n * A remote API, resolved.\n *\n * @internal\n */\nexport interface AuthioBffRemoteApi {\n readonly destination: string;\n readonly tokenMode: AuthioBffRemoteApiTokenMode;\n readonly resource: string | undefined;\n readonly scopes: readonly string[];\n readonly requireAntiForgery: boolean;\n readonly validateSessionOnUnauthorized: boolean;\n readonly fetch: typeof fetch;\n}\n\n/**\n * What forwarding needs from the BFF.\n *\n * @internal\n */\nexport interface AuthioBffRemoteApiContext {\n antiForgery(): boolean;\n readonly antiForgeryHeaderName: string;\n hasSession(): Promise<boolean>;\n userToken(): Promise<string | undefined>;\n clientToken(): Promise<string>;\n endIfInactive(): Promise<void>;\n}\n\nconst tokenModes: readonly AuthioBffRemoteApiTokenMode[] = [\"user\", \"userOrNone\", \"clientCredentials\", \"userOrClientCredentials\", \"none\"];\n\nconst hopByHop = new Set([\"connection\", \"keep-alive\", \"proxy-authenticate\", \"proxy-authorization\", \"proxy-connection\", \"te\", \"trailer\", \"transfer-encoding\", \"upgrade\"]);\n\nconst decodedEncodings = new Set([\"gzip\", \"x-gzip\", \"deflate\", \"br\"]);\n\n/**\n * Resolves and validates a remote API's settings.\n *\n * @throws AuthioConfigurationError when the destination is not an absolute HTTP(S) URL or the token mode is unknown.\n * @internal\n */\nexport function resolveRemoteApi(destination: string, options: AuthioBffRemoteApiOptions): AuthioBffRemoteApi {\n let url: URL;\n\n try {\n url = new URL(destination);\n } catch {\n throw new AuthioConfigurationError(`The remote API destination '${destination}' must be an absolute HTTP(S) URL.`);\n }\n\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\")\n throw new AuthioConfigurationError(`The remote API destination '${destination}' must be an absolute HTTP(S) URL.`);\n\n const tokenMode = options.tokenMode ?? \"user\";\n\n if (!tokenModes.includes(tokenMode)) throw new AuthioConfigurationError(`The remote API tokenMode must be one of ${tokenModes.join(\", \")}.`);\n\n const fetchImplementation = options.fetch ?? globalThis.fetch;\n\n if (typeof fetchImplementation !== \"function\") throw new AuthioConfigurationError(\"No fetch implementation is available: pass fetch to remoteApi.\");\n\n return {\n destination: destination.replace(/\\/+$/, \"\"),\n tokenMode,\n resource: options.resource?.trim() || undefined,\n scopes: [...(options.scopes ?? [])],\n requireAntiForgery: options.requireAntiForgery ?? true,\n validateSessionOnUnauthorized: options.validateSessionOnUnauthorized ?? true,\n fetch: fetchImplementation,\n };\n}\n\n/**\n * Forwards one call: enforces the anti-forgery header, obtains the token, maps the path below the mount point onto\n * the destination, strips the browser's cookies, the anti-forgery header and any `Authorization`, drops upstream\n * `Set-Cookie`, and after an upstream `401` to a user call checks the Authio session. An unreachable API answers `502`.\n *\n * @internal\n */\nexport async function forwardToRemoteApi(request: Request, response: Response, remote: AuthioBffRemoteApi, context: AuthioBffRemoteApiContext): Promise<void> {\n if (remote.requireAntiForgery && !context.antiForgery())\n return sendError(response, 401, \"antiforgery_required\", `The ${context.antiForgeryHeaderName} header is required.`);\n\n const token = await tokenFor(remote, context);\n\n if (token.refused) return sendError(response, 401, \"unauthorized\", \"Sign in first.\");\n\n const headers = outgoingHeaders(request, context.antiForgeryHeaderName);\n\n if (token.accessToken) headers.set(\"authorization\", `Bearer ${token.accessToken}`);\n\n let upstream: globalThis.Response;\n\n try {\n upstream = await remote.fetch(remote.destination + remainingUrl(request), {\n method: request.method,\n headers,\n body: outgoingBody(request),\n redirect: \"manual\",\n duplex: \"half\",\n } as RequestInit);\n } catch {\n return sendError(response, 502, \"bad_gateway\", \"The remote API could not be reached.\");\n }\n\n if (upstream.status === 401 && token.isUserToken && remote.validateSessionOnUnauthorized) await context.endIfInactive();\n\n if (response.headersSent) return;\n\n const encoding = upstream.headers.get(\"content-encoding\")?.trim().toLowerCase();\n const decoded = encoding !== undefined && decodedEncodings.has(encoding);\n\n response.status(upstream.status);\n\n upstream.headers.forEach((value, name) => {\n if (hopByHop.has(name) || name === \"set-cookie\" || (decoded && (name === \"content-encoding\" || name === \"content-length\"))) return;\n\n response.setHeader(name, value);\n });\n\n if (!upstream.body || request.method === \"HEAD\") {\n response.end();\n return;\n }\n\n await pipeline(Readable.fromWeb(upstream.body as NodeReadableStream), response);\n}\n\nasync function tokenFor(remote: AuthioBffRemoteApi, context: AuthioBffRemoteApiContext): Promise<{ refused: boolean; accessToken?: string; isUserToken?: boolean }> {\n switch (remote.tokenMode) {\n case \"none\":\n return { refused: false };\n case \"clientCredentials\":\n return { refused: false, accessToken: await context.clientToken() };\n default: {\n const userToken = (await context.hasSession()) ? await context.userToken() : undefined;\n\n if (userToken) return { refused: false, accessToken: userToken, isUserToken: true };\n if (remote.tokenMode === \"userOrNone\") return { refused: false };\n if (remote.tokenMode === \"userOrClientCredentials\") return { refused: false, accessToken: await context.clientToken() };\n\n return { refused: true };\n }\n }\n}\n\nfunction outgoingHeaders(request: Request, antiForgeryHeaderName: string): Headers {\n const headers = new Headers();\n const skipped = new Set([\n ...hopByHop,\n \"host\",\n \"cookie\",\n \"authorization\",\n \"content-length\",\n antiForgeryHeaderName.toLowerCase(),\n ...(request.headers.connection ?? \"\").split(\",\").map((name) => name.trim().toLowerCase()),\n ]);\n\n for (const [name, value] of Object.entries(request.headers)) {\n if (value === undefined || skipped.has(name)) continue;\n\n for (const item of Array.isArray(value) ? value : [value]) headers.append(name, item);\n }\n\n headers.set(\"accept-encoding\", \"identity\");\n\n return headers;\n}\n\nfunction outgoingBody(request: Request): BodyInit | undefined {\n const declaresBody = request.headers[\"transfer-encoding\"] !== undefined || Number(request.headers[\"content-length\"] ?? 0) > 0;\n\n if (request.method === \"GET\" || request.method === \"HEAD\" || !declaresBody) return undefined;\n\n const parsed = (request as Request & { body?: unknown }).body;\n\n if (!request.readableEnded) return Readable.toWeb(request) as unknown as BodyInit;\n if (parsed === undefined || parsed === null) return undefined;\n if (Buffer.isBuffer(parsed)) return new Uint8Array(parsed);\n if (typeof parsed === \"string\") return parsed;\n if ((request.headers[\"content-type\"] ?? \"\").toLowerCase().startsWith(\"application/x-www-form-urlencoded\"))\n return new URLSearchParams(parsed as Record<string, string>).toString();\n\n return JSON.stringify(parsed);\n}\n\nfunction remainingUrl(request: Request): string {\n const url = request.url || \"/\";\n const originalPath = new URL(request.originalUrl || url, \"http://localhost\").pathname;\n\n if ((url === \"/\" || url.startsWith(\"/?\")) && !originalPath.endsWith(\"/\")) return url.slice(1);\n\n return url;\n}\n","/**\n * Hands out one asynchronous lock per session, so concurrent requests of the same person never refresh the same\n * refresh token twice (Authio rotates it and treats a late reuse as a replay that revokes the session). The lock is\n * local to the process, as `AuthioBffSessionLockProvider` is in .NET: with several instances, keep a person on one\n * instance or rely on Authio's short reuse leeway.\n *\n * @internal\n */\nexport class AuthioBffSessionLocks {\n private readonly tails = new Map<string, { promise: Promise<void>; references: number }>();\n\n /** The number of keys with a holder or a waiter. */\n get size(): number {\n return this.tails.size;\n }\n\n /**\n * Runs `work` once every earlier holder of `key` released it, and releases it afterwards, even when `work` throws.\n */\n async run<T>(key: string, work: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n let release!: () => void;\n const turn = new Promise<void>((resolve) => {\n release = resolve;\n });\n const entry = { promise: (previous?.promise ?? Promise.resolve()).then(() => turn), references: (previous?.references ?? 0) + 1 };\n\n this.tails.set(key, entry);\n\n try {\n await previous?.promise;\n\n return await work();\n } finally {\n release();\n\n const current = this.tails.get(key);\n\n if (current) {\n current.references -= 1;\n if (current.references === 0) this.tails.delete(key);\n }\n }\n }\n}\n","import { systemClock, type AuthioClock } from \"@hyper.authio/client\";\n\n/**\n * A session as the store keeps it. `data` is encrypted by the BFF (AES-256-GCM, from `cookieSecret`): the store never\n * sees the tokens. `sessionId` and `subject` are kept in clear so back-channel logout can find the sessions to end.\n */\nexport interface AuthioBffStoredSession {\n /** The store key: `sessionKeyPrefix` followed by 64 random hex characters. The cookie carries the part after the prefix. */\n readonly key: string;\n /** The Authio session (`sid` of the ID token), when Authio named one. */\n readonly sessionId: string | undefined;\n /** The person (`sub`). */\n readonly subject: string | undefined;\n /** When the session expires, in milliseconds since the epoch; a store may drop it from then on. */\n readonly expiresAt: number;\n /** The encrypted session. */\n readonly data: string;\n}\n\n/**\n * Where the BFF keeps its sessions. The default is in memory (one process); implement this over Redis or a database for\n * several instances, indexing each session by `sessionId` and `subject` so back-channel logout can end them.\n * Every method may return a value or a promise.\n */\nexport interface AuthioBffSessionStore {\n /** Reads a session; `undefined` when it is unknown or expired. */\n get(key: string): AuthioBffStoredSession | undefined | Promise<AuthioBffStoredSession | undefined>;\n /** Creates or replaces a session, kept until `expiresAt`. */\n set(session: AuthioBffStoredSession): void | Promise<void>;\n /** Deletes a session. */\n delete(key: string): void | Promise<void>;\n /** Deletes every session of an Authio session (`sid`). */\n deleteBySessionId(sessionId: string): void | Promise<void>;\n /** Deletes every session of a person (`sub`). */\n deleteBySubject(subject: string): void | Promise<void>;\n}\n\n/**\n * Options of the in-memory store.\n */\nexport interface AuthioBffMemoryStoreOptions {\n /** The clock expiry is measured with. Defaults to the system clock. */\n clock?: AuthioClock;\n}\n\n/**\n * An in-memory session store, indexed by `sessionId` and `subject`, that drops expired sessions. Sessions live in one\n * process and are lost on restart: use a shared store for several instances.\n */\nexport interface AuthioBffMemoryStore extends AuthioBffSessionStore {\n /** The number of sessions held, expired ones included until they are swept. */\n readonly size: number;\n get(key: string): AuthioBffStoredSession | undefined;\n set(session: AuthioBffStoredSession): void;\n delete(key: string): void;\n deleteBySessionId(sessionId: string): void;\n deleteBySubject(subject: string): void;\n}\n\n/**\n * Creates the in-memory session store.\n */\nexport function createAuthioBffMemoryStore(options: AuthioBffMemoryStoreOptions = {}): AuthioBffMemoryStore {\n const clock = options.clock ?? systemClock;\n const sessions = new Map<string, AuthioBffStoredSession>();\n const bySessionId = new Map<string, Set<string>>();\n const bySubject = new Map<string, Set<string>>();\n let nextSweep = 0;\n\n const index = (lookup: Map<string, Set<string>>, value: string | undefined, key: string) => {\n if (!value) return;\n\n const keys = lookup.get(value) ?? new Set<string>();\n\n keys.add(key);\n lookup.set(value, keys);\n };\n\n const unindex = (lookup: Map<string, Set<string>>, value: string | undefined, key: string) => {\n if (!value) return;\n\n const keys = lookup.get(value);\n\n keys?.delete(key);\n if (keys?.size === 0) lookup.delete(value);\n };\n\n const remove = (key: string) => {\n const session = sessions.get(key);\n\n if (!session) return;\n\n sessions.delete(key);\n unindex(bySessionId, session.sessionId, key);\n unindex(bySubject, session.subject, key);\n };\n\n const sweep = () => {\n const now = clock.now();\n\n if (now < nextSweep) return;\n\n nextSweep = now + 60_000;\n\n for (const [key, session] of sessions) if (session.expiresAt <= now) remove(key);\n };\n\n return {\n get size() {\n return sessions.size;\n },\n get(key) {\n const session = sessions.get(key);\n\n if (!session) return undefined;\n if (session.expiresAt > clock.now()) return session;\n\n remove(key);\n\n return undefined;\n },\n set(session) {\n sweep();\n remove(session.key);\n sessions.set(session.key, session);\n index(bySessionId, session.sessionId, session.key);\n index(bySubject, session.subject, session.key);\n },\n delete: remove,\n deleteBySessionId(sessionId) {\n for (const key of [...(bySessionId.get(sessionId) ?? [])]) remove(key);\n },\n deleteBySubject(subject) {\n for (const key of [...(bySubject.get(subject) ?? [])]) remove(key);\n },\n };\n}\n","import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport type { NextFunction, Request, RequestHandler, Response } from \"express\";\nimport {\n AuthioDefaults,\n AuthioError,\n AuthioOAuthErrors,\n AuthioPrompts,\n AuthioProtocolError,\n AuthioTokenTypes,\n createAuthioClient,\n type AuthioAuthorizationTransaction,\n type AuthioClient,\n type AuthioClientOptions,\n type AuthioPrompt,\n} from \"@hyper.authio/client\";\nimport { mergeUserInfo, replaceAccessTokenClaims, toAuthioBffClaims, toSessionClaims } from \"./claims.js\";\nimport { hasAntiForgeryHeader, readCookies, readFormField, readQuery, requestBase, sendError, setCookie, withQueryParameter } from \"./http.js\";\nimport { AuthioBffDefaults, isLocalUrl, resolveBffSettings, type AuthioBffOptions } from \"./options.js\";\nimport { createAuthioBffProtector } from \"./protection.js\";\nimport { forwardToRemoteApi, resolveRemoteApi, type AuthioBffRemoteApiOptions } from \"./remote-api.js\";\nimport { AuthioBffSessionLocks } from \"./session-locks.js\";\nimport { createAuthioBffMemoryStore, type AuthioBffSessionStore } from \"./session-store.js\";\n\n/**\n * The signed-in session as the application sees it: who, which Authio session, until when. Never the tokens.\n */\nexport interface AuthioBffSessionInfo {\n /** The person (`sub`). */\n readonly subject: string | undefined;\n /** The Authio session (`sid`). */\n readonly sessionId: string | undefined;\n /**\n * The session's claims: the ID token's, the access token's `*_resource_access` and organization (read from the\n * token or its introspection, as `accessTokenClaims` says), UserInfo's.\n */\n readonly claims: Readonly<Record<string, unknown>>;\n /** When the BFF session expires, in milliseconds since the epoch. */\n readonly expiresAt: number;\n}\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Express {\n interface Request {\n /** The Authio BFF session, once the BFF read it for this request; `undefined` when nobody is signed in. */\n authioBff?: AuthioBffSessionInfo;\n }\n }\n}\n\n/**\n * Options of `bff.api()`.\n */\nexport interface AuthioBffApiOptions {\n /** Requires the anti-forgery header. Defaults to `true`. */\n requireAntiForgery?: boolean;\n /** Lets anonymous calls through (with `req.authioBff` undefined) instead of answering `401`. Defaults to `false`. */\n optional?: boolean;\n}\n\n/**\n * What a user token is asked for: a resource (RFC 8707) and/or narrower scopes make the BFF exchange the session's\n * token (RFC 8693) and cache the result per session, resource and scopes.\n */\nexport interface AuthioBffUserTokenOptions {\n /** The resource the token must be issued for. */\n resource?: string;\n /** The scopes the token must carry. */\n scopes?: readonly string[];\n}\n\n/**\n * The Authio BFF: an Express middleware serving the BFF endpoints, plus the helpers the application's own routes use.\n */\nexport interface AuthioBff extends RequestHandler {\n /** The Authio client the BFF talks to Authio with. */\n readonly client: AuthioClient;\n /** Where the sessions live. */\n readonly store: AuthioBffSessionStore;\n /**\n * Marks a local API: requires the anti-forgery header (`401 antiforgery_required`) and a session (`401\n * unauthorized`), never redirects, and sets `req.authioBff`.\n */\n api(options?: AuthioBffApiOptions): RequestHandler;\n /**\n * Forwards the calls mounted under a path to a remote API with the token `tokenMode` asks for:\n * `app.use(\"/api/orders\", bff.remoteApi(\"https://orders.example.com\"))`. Mount it before any body parser.\n */\n remoteApi(destination: string, options?: AuthioBffRemoteApiOptions): RequestHandler;\n /** Reads the request's session (once per request), checking and renewing it as configured. */\n getSession(request: Request, response: Response): Promise<AuthioBffSessionInfo | undefined>;\n /**\n * The person's access token, refreshed `tokenRefreshSkew` before it expires (one refresh per session at a time), or\n * exchanged for `resource`/`scopes`. `undefined` when nobody is signed in or the session ended (a refused refresh\n * ends it).\n */\n getUserAccessToken(request: Request, response: Response, options?: AuthioBffUserTokenOptions): Promise<string | undefined>;\n /** A `fetch` that sends the person's access token (see `getUserAccessToken`), for calling APIs from a route. */\n userFetch(request: Request, response: Response, options?: AuthioBffUserTokenOptions & { fetch?: typeof fetch }): typeof fetch;\n /** Ends the request's session locally: deletes it from the store and clears the cookie. Authio is not told. */\n endSession(request: Request, response: Response): Promise<void>;\n}\n\ninterface SessionData {\n publicId: string;\n claims: Record<string, unknown>;\n accessToken?: string;\n accessTokenExpiresAt?: number;\n refreshToken?: string;\n idToken?: string;\n tokenType?: string;\n resource?: string;\n createdAt: number;\n validatedAt: number;\n}\n\ninterface LoadedSession {\n readonly key: string;\n readonly expiresAt: number;\n readonly data: SessionData;\n}\n\ninterface LoginState {\n transaction: AuthioAuthorizationTransaction;\n returnUrl: string;\n expiresAt: number;\n}\n\ninterface LoginParameters {\n returnUrl: string;\n prompt?: AuthioPrompt;\n loginHint?: string;\n uiLocales?: string;\n maxAge?: number;\n organization?: string;\n resource?: string;\n}\n\ninterface ExchangedToken {\n readonly sessionKey: string;\n readonly accessToken: string;\n readonly refreshAt: number;\n readonly expiresAt: number;\n}\n\nconst sessionSlot = Symbol.for(\"authio.bff.session\");\n\ntype RequestWithSession = Request & { [sessionSlot]?: Promise<LoadedSession | undefined> };\n\n/**\n * Creates the Authio BFF. Mount it with `app.use(bff)`: it serves `{endpointPrefix}/login`, `/logout`, `/user`,\n * `/silent-login`, `/silent-login-callback`, `/backchannel-logout`, `/frontchannel-logout` (when turned on), the sign-in\n * callback (`callbackPath`) and the sign-out callback (`signedOutCallbackPath`), and reads the session of every other\n * request that carries the cookie.\n *\n * @throws AuthioConfigurationError naming every invalid option.\n */\nexport function authioBff(options: AuthioBffOptions): AuthioBff {\n const settings = resolveBffSettings(options);\n const client = options.client ?? createAuthioClient(options as AuthioClientOptions);\n const clock = client.connection.clock;\n const store = options.store ?? createAuthioBffMemoryStore({ clock });\n const protector = createAuthioBffProtector(settings.cookieSecrets);\n const locks = new AuthioBffSessionLocks();\n const exchanges = new Map<string, ExchangedToken>();\n const prefix = settings.endpointPrefix;\n const loginLifetimeMs = AuthioBffDefaults.LoginLifetime * 1000;\n\n const loginCookieName = (state: string | undefined) =>\n state ? `${settings.cookieName}.login.${createHash(\"sha256\").update(state).digest(\"base64url\").slice(0, 16)}` : `${settings.cookieName}.login`;\n\n const toInfo = (session: LoadedSession): AuthioBffSessionInfo =>\n Object.freeze({\n subject: textOf(session.data.claims.sub),\n sessionId: textOf(session.data.claims.sid),\n claims: Object.freeze({ ...session.data.claims }),\n expiresAt: session.expiresAt,\n });\n\n const expose = (request: Request, session: LoadedSession | undefined) => {\n (request as RequestWithSession)[sessionSlot] = Promise.resolve(session);\n request.authioBff = session ? toInfo(session) : undefined;\n };\n\n const read = async (key: string): Promise<LoadedSession | undefined> => {\n const stored = await store.get(key);\n\n if (!stored || stored.expiresAt <= clock.now()) return undefined;\n\n const data = protector.open<SessionData>(\"session-data\", stored.data);\n\n return data ? { key, expiresAt: stored.expiresAt, data } : undefined;\n };\n\n const write = async (key: string, data: SessionData, expiresAt: number): Promise<LoadedSession> => {\n await store.set({ key, sessionId: textOf(data.claims.sid), subject: textOf(data.claims.sub), expiresAt, data: protector.seal(\"session-data\", data) });\n\n return { key, expiresAt, data };\n };\n\n const update = (key: string, change: (session: LoadedSession) => { data: SessionData; expiresAt: number }) =>\n locks.run(key, async () => {\n const current = await read(key);\n\n if (!current) return undefined;\n\n const next = change(current);\n\n return write(key, next.data, next.expiresAt);\n });\n\n const dropExchanges = (key: string) => {\n for (const [cacheKey, entry] of exchanges) if (entry.sessionKey === key) exchanges.delete(cacheKey);\n };\n\n const clearCookie = (response: Response) => setCookie(response, settings.cookieName, \"\", settings.cookieSameSite, 0);\n\n const endSessionByKey = async (request: Request, response: Response, key: string) => {\n await store.delete(key);\n dropExchanges(key);\n clearCookie(response);\n expose(request, undefined);\n };\n\n const report = (error: unknown) => {\n try {\n settings.onError(error);\n } catch {\n return;\n }\n };\n\n const readAccessToken = async (accessToken: string): Promise<Record<string, unknown> | undefined> => {\n try {\n return await client.readAccessTokenClaims(accessToken);\n } catch (error) {\n report(error);\n\n return undefined;\n }\n };\n\n const introspectAccessToken = async (accessToken: string): Promise<Record<string, unknown>> => {\n const { active, ...claims } = await client.introspect(accessToken, { tokenTypeHint: AuthioTokenTypes.AccessToken });\n\n if (active !== true) throw new InactiveAccessTokenError();\n\n return claims;\n };\n\n /**\n * An opaque access token's claims under `accessTokenClaims: \"token\"`: Authio reports a token requested for a resource\n * as active only to that resource server's introspection client, so an inactive answer contributes nothing, as\n * before. A failed introspection (an error status, a timeout, the network) still throws.\n */\n const introspectOpaqueAccessToken = async (accessToken: string): Promise<Record<string, unknown> | undefined> => {\n try {\n return await introspectAccessToken(accessToken);\n } catch (error) {\n if (error instanceof InactiveAccessTokenError) return undefined;\n\n throw error;\n }\n };\n\n /**\n * The claims only the access token carries. With `accessTokenClaims: \"introspection\"` they come from introspection,\n * and a failure or an inactive answer throws. Otherwise they come from the verified token, which contributes nothing\n * when it does not verify (reported to `onError`), or, for an opaque token, from introspection, where only a failure\n * throws and an inactive answer contributes nothing.\n */\n const accessTokenClaimsOf = async (accessToken: string | undefined): Promise<Record<string, unknown> | undefined> => {\n if (!accessToken) return undefined;\n if (settings.accessTokenClaims === \"introspection\") return introspectAccessToken(accessToken);\n if (isReferenceToken(accessToken)) return introspectOpaqueAccessToken(accessToken);\n\n return readAccessToken(accessToken);\n };\n\n const refusesIdToken = async (idToken: string, accessToken: string, subject: unknown): Promise<boolean> => {\n try {\n const claims = await client.validateIdToken(idToken, { accessToken });\n\n if (typeof subject === \"string\" && claims.sub !== subject)\n throw new AuthioError(`The ID token of the refresh names '${claims.sub}', not the session's person.`);\n\n return false;\n } catch (error) {\n report(error);\n\n return true;\n }\n };\n\n const isActive = async (data: SessionData): Promise<boolean | undefined> => {\n const token = data.refreshToken ?? data.accessToken;\n\n if (!token) return undefined;\n\n try {\n const result = await client.introspect(token, { tokenTypeHint: data.refreshToken ? AuthioTokenTypes.RefreshToken : AuthioTokenTypes.AccessToken });\n\n return result.active === true;\n } catch (error) {\n report(error);\n\n return undefined;\n }\n };\n\n const maintain = async (request: Request, response: Response, session: LoadedSession): Promise<LoadedSession | undefined> => {\n const now = clock.now();\n const validate = settings.sessionValidation === \"introspection\" && now - session.data.validatedAt >= settings.sessionValidationIntervalMs;\n const slide = settings.slidingExpiration && session.expiresAt - now < settings.sessionLifetimeMs / 2;\n let validated = false;\n\n if (validate) {\n const active = await isActive(session.data);\n\n if (active === false) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n validated = active === true;\n }\n\n if (!validated && !slide) return session;\n\n const renewed = await update(session.key, (current) => ({\n data: validated ? { ...current.data, validatedAt: now } : current.data,\n expiresAt: slide ? now + settings.sessionLifetimeMs : current.expiresAt,\n }));\n\n return renewed;\n };\n\n const loadSession = (request: Request, response: Response): Promise<LoadedSession | undefined> => {\n const holder = request as RequestWithSession;\n const cached = holder[sessionSlot];\n\n if (cached) return cached;\n\n const loading = (async () => {\n const cookie = readCookies(request).get(settings.cookieName);\n\n if (!cookie) return undefined;\n\n const id = protector.unsign(cookie);\n const found = id ? await read(settings.sessionKeyPrefix + id) : undefined;\n const session = found ? await maintain(request, response, found) : undefined;\n\n if (!session) {\n clearCookie(response);\n request.authioBff = undefined;\n return undefined;\n }\n\n request.authioBff = toInfo(session);\n\n return session;\n })();\n\n holder[sessionSlot] = loading;\n\n return loading;\n };\n\n const isFresh = (data: SessionData, skewMs: number) =>\n Boolean(data.accessToken) && (data.accessTokenExpiresAt === undefined || clock.now() < data.accessTokenExpiresAt - skewMs);\n\n /**\n * The access token claims of a refresh, or `\"inactive\"` when, with `accessTokenClaims: \"introspection\"`, Authio\n * reports the new access token as not active, which ends the session. The refresh token may already be rotated, so\n * any other failure keeps the session's previous claims (reported to `onError`) rather than the previous tokens.\n */\n const refreshedAccessTokenClaims = async (accessToken: string): Promise<Record<string, unknown> | \"inactive\" | undefined> => {\n try {\n return await accessTokenClaimsOf(accessToken);\n } catch (error) {\n if (error instanceof InactiveAccessTokenError) return \"inactive\";\n\n report(error);\n\n return undefined;\n }\n };\n\n const refresh = async (request: Request, response: Response, session: LoadedSession): Promise<string | undefined> => {\n const data = { ...session.data, claims: { ...session.data.claims } };\n const unexpired = isFresh(data, 0) ? data.accessToken : undefined;\n\n if (!data.refreshToken) return unexpired;\n\n try {\n const issuedAt = clock.now();\n const answer = await client.tokens.refresh({ refreshToken: data.refreshToken });\n\n if (answer.id_token && (await refusesIdToken(answer.id_token, answer.access_token, data.claims.sub))) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n data.accessToken = answer.access_token;\n data.accessTokenExpiresAt = issuedAt + lifetimeOf(answer.expires_in);\n data.tokenType = answer.token_type ?? data.tokenType;\n if (answer.refresh_token) data.refreshToken = answer.refresh_token;\n if (answer.id_token) data.idToken = answer.id_token;\n\n const accessClaims = await refreshedAccessTokenClaims(answer.access_token);\n\n if (accessClaims === \"inactive\" || !(await store.get(session.key))) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n replaceAccessTokenClaims(data.claims, accessClaims);\n expose(request, await write(session.key, data, session.expiresAt));\n\n return answer.access_token;\n } catch (error) {\n report(error);\n\n if (error instanceof AuthioProtocolError && error.error === AuthioOAuthErrors.InvalidGrant) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n return unexpired;\n }\n };\n\n const sessionAccessToken = async (request: Request, response: Response): Promise<string | undefined> => {\n const session = await loadSession(request, response);\n\n if (!session) return undefined;\n if (isFresh(session.data, settings.tokenRefreshSkewMs)) return session.data.accessToken;\n\n return locks.run(session.key, async () => {\n const current = await read(session.key);\n\n if (!current) {\n await endSessionByKey(request, response, session.key);\n return undefined;\n }\n\n if (isFresh(current.data, settings.tokenRefreshSkewMs)) {\n expose(request, current);\n return current.data.accessToken;\n }\n\n return refresh(request, response, current);\n });\n };\n\n const getUserAccessToken: AuthioBff[\"getUserAccessToken\"] = async (request, response, tokenOptions = {}) => {\n const scopes = [...new Set((tokenOptions.scopes ?? []).map((scope) => scope.trim()).filter(Boolean))].sort();\n const resource = tokenOptions.resource?.trim() || undefined;\n const subjectToken = await sessionAccessToken(request, response);\n\n if (!subjectToken || (!resource && scopes.length === 0)) return subjectToken;\n\n const session = await loadSession(request, response);\n\n if (!session) return undefined;\n\n const cacheKey = `${session.key}|${resource ?? \"\"}|${scopes.join(\" \")}`;\n const cached = exchanges.get(cacheKey);\n\n if (cached && clock.now() < cached.refreshAt) return cached.accessToken;\n\n return locks.run(cacheKey, async () => {\n const again = exchanges.get(cacheKey);\n\n if (again && clock.now() < again.refreshAt) return again.accessToken;\n\n const issuedAt = clock.now();\n const answer = await client.tokens.exchange({ subjectToken, scopes: scopes.length > 0 ? scopes : undefined, resource });\n const lifetime = lifetimeOf(answer.expires_in);\n\n for (const [key, entry] of exchanges) if (entry.expiresAt <= issuedAt) exchanges.delete(key);\n\n exchanges.set(cacheKey, {\n sessionKey: session.key,\n accessToken: answer.access_token,\n refreshAt: issuedAt + lifetime - Math.min(settings.tokenRefreshSkewMs, lifetime / 2),\n expiresAt: issuedAt + lifetime,\n });\n\n return answer.access_token;\n });\n };\n\n const endIfInactive = async (request: Request, response: Response) => {\n const session = await loadSession(request, response);\n\n if (session && (await isActive(session.data)) === false) await endSessionByKey(request, response, session.key);\n };\n\n const antiForgery = (request: Request) => hasAntiForgeryHeader(request, settings.antiForgeryHeaderName, settings.antiForgeryHeaderValue);\n\n const antiForgeryRequired = (response: Response) =>\n sendError(response, 401, \"antiforgery_required\", `The ${settings.antiForgeryHeaderName} header is required.`);\n\n const startLogin = async (request: Request, response: Response, parameters: LoginParameters) => {\n const { url, transaction } = await client.createAuthorizationUrl({\n redirectUri: settings.redirectUri ?? requestBase(request) + settings.callbackPath,\n checks: options.checks,\n codeChallengeMethod: options.codeChallengeMethod,\n responseMode: options.responseMode,\n scopes: settings.scopes,\n resource: parameters.resource ?? settings.resource,\n organization: parameters.organization ?? settings.organization,\n prompt: parameters.prompt ?? settings.prompt,\n loginHint: parameters.loginHint,\n uiLocales: parameters.uiLocales ?? settings.uiLocales,\n maxAge: parameters.maxAge ?? settings.maxAge,\n extraParameters: settings.additionalAuthorizationParameters,\n });\n const state: LoginState = { transaction, returnUrl: parameters.returnUrl, expiresAt: clock.now() + loginLifetimeMs };\n\n setCookie(response, loginCookieName(transaction.state), protector.seal(\"login\", state), \"lax\", AuthioBffDefaults.LoginLifetime);\n response.set(\"Cache-Control\", \"no-store\").redirect(302, url);\n };\n\n const login = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const returnUrl = query.get(\"returnUrl\") ?? \"\";\n const prompt = query.get(\"prompt\") ?? \"\";\n const maxAge = query.get(\"max_age\") ?? \"\";\n const resource = query.get(\"resource\") ?? \"\";\n\n if (returnUrl && !isLocalUrl(returnUrl)) return sendError(response, 400, \"invalid_request\", \"returnUrl must be a local URL.\");\n if (prompt && !(AuthioPrompts as readonly string[]).includes(prompt))\n return sendError(response, 400, \"invalid_request\", \"prompt must be none, login, select_account or consent.\");\n if (maxAge && !/^\\d+$/.test(maxAge)) return sendError(response, 400, \"invalid_request\", \"max_age must be a number of seconds.\");\n if (resource && resource !== settings.resource && !settings.allowedResources.includes(resource))\n return sendError(response, 400, \"invalid_target\", \"The resource is not allowed by allowedResources.\");\n\n await startLogin(request, response, {\n returnUrl: returnUrl || settings.defaultReturnUrl,\n prompt: (prompt || undefined) as AuthioPrompt | undefined,\n loginHint: query.get(\"login_hint\") || undefined,\n uiLocales: query.get(\"ui_locales\") || undefined,\n maxAge: maxAge ? Number(maxAge) : undefined,\n organization: query.get(\"organization\") || undefined,\n resource: resource || undefined,\n });\n };\n\n const silentLogin = (request: Request, response: Response) =>\n startLogin(request, response, { returnUrl: `${request.baseUrl ?? \"\"}${prefix}/silent-login-callback`, prompt: \"none\" });\n\n const callback = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const state = query.get(\"state\") || undefined;\n const cookies = readCookies(request);\n const cookieName = [loginCookieName(state), loginCookieName(undefined)].find((name) => cookies.has(name));\n const sealed = cookieName ? cookies.get(cookieName) : undefined;\n const pending = sealed ? protector.open<LoginState>(\"login\", sealed) : undefined;\n\n if (cookieName && sealed) setCookie(response, cookieName, \"\", \"lax\", 0);\n\n response.set(\"Cache-Control\", \"no-store\");\n\n const fail = (target: string, error: string) => response.redirect(302, withQueryParameter(target, \"error\", error));\n\n if (!pending || (pending.transaction?.state !== undefined && pending.transaction.state !== state) || pending.expiresAt <= clock.now())\n return fail(settings.defaultReturnUrl, \"login_failed\");\n\n const target = isLocalUrl(pending.returnUrl) ? pending.returnUrl : settings.defaultReturnUrl;\n\n if (settings.requireIssuerParameter && !query.has(\"iss\") && !query.has(\"error\")) return fail(target, \"login_failed\");\n\n let data: SessionData;\n\n try {\n const { tokens, idToken } = await client.handleAuthorizationCallback(query, pending.transaction);\n const now = clock.now();\n const accessClaims = await accessTokenClaimsOf(tokens.access_token);\n const claims = toSessionClaims(idToken, textOf(accessClaims?.sub));\n\n replaceAccessTokenClaims(claims, accessClaims);\n\n if (settings.getClaimsFromUserInfoEndpoint) mergeUserInfo(claims, await client.userInfo(tokens.access_token));\n\n data = {\n publicId: randomBytes(16).toString(\"hex\"),\n claims,\n accessToken: tokens.access_token,\n accessTokenExpiresAt: now + lifetimeOf(tokens.expires_in),\n refreshToken: tokens.refresh_token,\n idToken: tokens.id_token,\n tokenType: tokens.token_type,\n resource: pending.transaction.resource,\n createdAt: now,\n validatedAt: now,\n };\n } catch (error) {\n report(error);\n\n return fail(target, error instanceof AuthioProtocolError ? error.error : \"login_failed\");\n }\n\n const previous = readCookies(request).get(settings.cookieName);\n const previousId = previous ? protector.unsign(previous) : undefined;\n\n if (previousId) {\n await store.delete(settings.sessionKeyPrefix + previousId);\n dropExchanges(settings.sessionKeyPrefix + previousId);\n }\n\n const id = randomBytes(32).toString(\"hex\");\n\n expose(request, await write(settings.sessionKeyPrefix + id, data, clock.now() + settings.sessionLifetimeMs));\n setCookie(response, settings.cookieName, protector.sign(id), settings.cookieSameSite);\n response.redirect(302, target);\n };\n\n const user = async (request: Request, response: Response) => {\n if (!antiForgery(request)) return antiForgeryRequired(response);\n\n const session = await loadSession(request, response);\n\n if (!session) return sendError(response, 401, \"unauthorized\", \"Nobody is signed in.\");\n\n const expiresIn = Math.max(0, Math.floor((session.expiresAt - clock.now()) / 1000));\n const logoutUrl = `${request.baseUrl ?? \"\"}${prefix}/logout?sid=${encodeURIComponent(session.data.publicId)}`;\n\n response.set(\"Cache-Control\", \"no-store\").json(toAuthioBffClaims(session.data.claims, expiresIn, logoutUrl));\n };\n\n const logout = async (request: Request, response: Response) => {\n const query = readQuery(request);\n const returnUrl = query.get(\"returnUrl\") ?? \"\";\n\n if (returnUrl && !isLocalUrl(returnUrl)) return sendError(response, 400, \"invalid_request\", \"returnUrl must be a local URL.\");\n\n const target = returnUrl || settings.defaultReturnUrl;\n const session = await loadSession(request, response);\n\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!session) {\n clearCookie(response);\n return response.redirect(302, target);\n }\n\n if (!antiForgery(request) && !fixedTimeEquals(query.get(\"sid\") ?? \"\", session.data.publicId))\n return sendError(response, 400, \"invalid_request\", `Logging out requires the ${settings.antiForgeryHeaderName} header or the session's sid parameter.`);\n\n if (settings.revokeRefreshTokenOnLogout && session.data.refreshToken) {\n try {\n await client.revoke(session.data.refreshToken, { tokenTypeHint: AuthioTokenTypes.RefreshToken });\n } catch (error) {\n report(error);\n }\n }\n\n await endSessionByKey(request, response, session.key);\n\n const document = await client.discovery.get();\n\n if (!document.end_session_endpoint) return response.redirect(302, target);\n\n const endSessionUrl = await client.createEndSessionUrl({\n idTokenHint: session.data.idToken,\n postLogoutRedirectUri: settings.postLogoutRedirectUri ?? requestBase(request) + settings.signedOutCallbackPath,\n state: protector.seal(\"logout-state\", { returnUrl: target, expiresAt: clock.now() + loginLifetimeMs }),\n uiLocales: settings.uiLocales,\n });\n\n response.redirect(302, endSessionUrl);\n };\n\n const signedOutCallback = (request: Request, response: Response) => {\n const state = readQuery(request).get(\"state\");\n const value = state ? protector.open<{ returnUrl: string; expiresAt: number }>(\"logout-state\", state) : undefined;\n const target = value && value.expiresAt > clock.now() && isLocalUrl(value.returnUrl) ? value.returnUrl : settings.defaultReturnUrl;\n\n response.set(\"Cache-Control\", \"no-store\").redirect(302, target);\n };\n\n const silentLoginCallback = async (request: Request, response: Response) => {\n const session = await loadSession(request, response);\n const error = readQuery(request).get(\"error\") || null;\n const message = JSON.stringify({ source: AuthioBffDefaults.SilentLoginMessageSource, isLoggedIn: Boolean(session) && !error, error }).replace(\n /[^ -~]|[<>&]/g,\n (character) => `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n response\n .set(\"Cache-Control\", \"no-store\")\n .type(\"text/html; charset=utf-8\")\n .send(\n `<!doctype html><html><head><meta charset=\"utf-8\"><title>Authio</title></head><body><script>(function(){var m=${message};(window.parent!==window?window.parent:window.opener||window).postMessage(m,window.location.origin);})();</script></body></html>`,\n );\n };\n\n const backChannelLogout = async (request: Request, response: Response) => {\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!settings.backChannelLogout) return void response.status(404).end();\n\n const token = await readFormField(request, \"logout_token\");\n\n if (!token?.trim()) return sendError(response, 400, \"invalid_request\", \"The logout_token form field is required.\");\n\n let logout;\n\n try {\n logout = await client.validateLogoutToken(token);\n } catch (error) {\n report(error);\n\n if (!(error instanceof AuthioError)) throw error;\n\n return sendError(response, 400, \"invalid_request\", \"The logout token is not valid.\");\n }\n\n if (logout.sessionId) await store.deleteBySessionId(logout.sessionId);\n else if (logout.subject) await store.deleteBySubject(logout.subject);\n\n response.status(200).end();\n };\n\n const frontChannelLogout = async (request: Request, response: Response) => {\n response.set(\"Cache-Control\", \"no-store\");\n\n if (!settings.frontChannelLogout) return void response.status(404).end();\n\n let sessionId: string | undefined;\n\n try {\n sessionId = client.validateFrontChannelLogout(readQuery(request)).sessionId;\n } catch (error) {\n report(error);\n\n if (!(error instanceof AuthioError)) throw error;\n\n return sendError(response, 400, \"invalid_request\", \"The front-channel logout request is not valid.\");\n }\n\n const cookie = readCookies(request).get(settings.cookieName);\n const id = cookie ? protector.unsign(cookie) : undefined;\n const key = id ? settings.sessionKeyPrefix + id : undefined;\n\n if (sessionId) await store.deleteBySessionId(sessionId);\n else if (key) {\n await store.delete(key);\n dropExchanges(key);\n }\n\n if (key && !(await store.get(key))) clearCookie(response);\n\n response\n .status(200)\n .type(\"text/html; charset=utf-8\")\n .send('<!doctype html><html><head><meta charset=\"utf-8\"><title>Authio</title></head><body></body></html>');\n };\n\n const routes = new Map<string, { methods: readonly string[]; run: (request: Request, response: Response) => unknown }>([\n [settings.callbackPath, { methods: [\"GET\"], run: callback }],\n [settings.signedOutCallbackPath, { methods: [\"GET\"], run: signedOutCallback }],\n [`${prefix}/login`, { methods: [\"GET\"], run: login }],\n [`${prefix}/logout`, { methods: [\"GET\", \"POST\"], run: logout }],\n [`${prefix}/user`, { methods: [\"GET\"], run: user }],\n [`${prefix}/silent-login`, { methods: [\"GET\"], run: silentLogin }],\n [`${prefix}/silent-login-callback`, { methods: [\"GET\"], run: silentLoginCallback }],\n [`${prefix}/backchannel-logout`, { methods: [\"POST\"], run: backChannelLogout }],\n [`${prefix}/frontchannel-logout`, { methods: [\"GET\"], run: frontChannelLogout }],\n ]);\n\n const middleware = (request: Request, response: Response, next: NextFunction) => {\n const route = routes.get(request.path.replace(/(.)\\/+$/, \"$1\"));\n\n if (route && route.methods.includes(request.method)) {\n Promise.resolve()\n .then(() => route.run(request, response))\n .catch(next);\n return;\n }\n\n loadSession(request, response).then(() => next(), next);\n };\n\n const bff = middleware as AuthioBff;\n\n return Object.assign(bff, {\n client,\n store,\n api(apiOptions: AuthioBffApiOptions = {}): RequestHandler {\n return (request, response, next) => {\n if (apiOptions.requireAntiForgery !== false && !antiForgery(request)) return antiForgeryRequired(response);\n\n loadSession(request, response).then((session) => {\n if (!session && !apiOptions.optional) return sendError(response, 401, \"unauthorized\", \"Sign in first.\");\n\n next();\n }, next);\n };\n },\n remoteApi(destination: string, remoteOptions: AuthioBffRemoteApiOptions = {}): RequestHandler {\n const remote = resolveRemoteApi(destination, remoteOptions);\n\n return (request, response, next) => {\n forwardToRemoteApi(request, response, remote, {\n antiForgery: () => antiForgery(request),\n antiForgeryHeaderName: settings.antiForgeryHeaderName,\n hasSession: async () => Boolean(await loadSession(request, response)),\n userToken: () => getUserAccessToken(request, response, { resource: remote.resource, scopes: remote.scopes }),\n clientToken: async () => (await client.clientCredentials.getToken({ scopes: remote.scopes, resource: remote.resource })).accessToken,\n endIfInactive: () => endIfInactive(request, response),\n }).catch(next);\n };\n },\n async getSession(request: Request, response: Response) {\n const session = await loadSession(request, response);\n\n return session ? toInfo(session) : undefined;\n },\n getUserAccessToken,\n userFetch(request: Request, response: Response, fetchOptions: AuthioBffUserTokenOptions & { fetch?: typeof fetch } = {}): typeof fetch {\n const inner = fetchOptions.fetch ?? client.connection.fetch;\n\n return async (input, init) => {\n const token = await getUserAccessToken(request, response, fetchOptions);\n const headers = new Headers(init?.headers ?? (input instanceof globalThis.Request ? input.headers : undefined));\n\n if (token) headers.set(\"authorization\", `Bearer ${token}`);\n\n return inner(input, { ...init, headers });\n };\n },\n async endSession(request: Request, response: Response) {\n const session = await loadSession(request, response);\n\n if (session) await endSessionByKey(request, response, session.key);\n },\n });\n}\n\nfunction lifetimeOf(expiresIn: number | undefined): number {\n return (expiresIn && expiresIn > 0 ? expiresIn : AuthioDefaults.AssumedTokenLifetime) * 1000;\n}\n\nfunction textOf(value: unknown): string | undefined {\n return typeof value === \"string\" && value ? value : undefined;\n}\n\n/** Introspection reports the session's access token as not active: a failed sign-in, or a session that ended. */\nclass InactiveAccessTokenError extends AuthioError {\n constructor() {\n super(\"Authio reports the session's access token as not active, so its claims cannot be read.\");\n }\n}\n\n/** Whether an access token is an opaque reference (Authio's handle has no dot), which only introspection resolves. */\nfunction isReferenceToken(token: string): boolean {\n return !token.includes(\".\");\n}\n\nfunction fixedTimeEquals(left: string, right: string): boolean {\n const a = Buffer.from(left, \"utf8\");\n const b = Buffer.from(right, \"utf8\");\n\n return a.length > 0 && a.length === b.length && timingSafeEqual(a, b);\n}\n\n"]}
|