3.2 KiB
csrf-policy — CsrfPolicy.requiresCsrf
(no submodules)
Purpose
Exposes a single pure predicate, CsrfPolicy.requiresCsrf(scheme), that
defaults CSRF protection ON for any cookie-based scheme and OFF for any scheme
where the caller must actively attach the credential. This default codifies the
design-doc §6 rule "Cookie-based auth adapters trigger CSRF verification" so
every concrete adapter inherits the right behaviour without restating it.
The package exposes only the default; the host (api-host) applies per-route
csrf: false overrides on top. Keeping the default and the override separate
means a route-level opt-out is always auditable as an explicit decision in the
manifest, never a side-effect of which adapter happened to be wired.
Features
- Pure function — no side effects, no module-load cost.
- Frozen container object so test code can
expect(CsrfPolicy)reliably and consumers cannot monkey-patch the predicate. - Total over the
OpenApiSecuritySchemediscriminated union — nodefaultbranch means an added scheme type at the schema layer will surface a type-level reminder to revisit the policy.
Usage: Basic
import { CsrfPolicy } from "@suaveplan/api-auth/csrf-policy";
const needsCsrf = CsrfPolicy.requiresCsrf({
type: "apiKey",
in: "cookie",
name: "sp_session",
}); // → true
Usage: Advanced
Drive a host-side CSRF middleware off the policy, with a per-route override applied at the call site:
import { CsrfPolicy } from "@suaveplan/api-auth/csrf-policy";
import type { OpenApiSecurityScheme } from "@suaveplan/api-auth/security-scheme";
interface RouteCsrfDecision {
readonly required: boolean;
readonly reason: "scheme-default" | "route-override";
}
function decideCsrf(
scheme: OpenApiSecurityScheme,
routeOverride: boolean | undefined,
): RouteCsrfDecision {
if (routeOverride !== undefined) {
return { required: routeOverride, reason: "route-override" };
}
return {
required: CsrfPolicy.requiresCsrf(scheme),
reason: "scheme-default",
};
}
const decision = decideCsrf(
{ type: "http", scheme: "bearer" },
undefined,
);
// → { required: false, reason: "scheme-default" }
API Reference
| Symbol | Kind | Description |
|---|---|---|
CsrfPolicy.requiresCsrf |
function | (scheme) => boolean. Cookie schemes → true. |
Implementation Notes
- The predicate inspects
type === "apiKey" && in === "cookie"— apiKey-in- header is treated identically toAuthorization: Bearer …for CSRF purposes because the caller must attach it explicitly. oauth2andopenIdConnectdefault OFF — both are bearer-token-derived in practice; if a deployment exposes an oauth2 access token via cookie, that's a custom apiKey-in-cookie scheme, not theoauth2scheme.Object.freezeguards the predicate slot; the predicate itself is a regular method and TypeScript prevents reassignment via theReadonlyinference.