Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.4 KiB
@suaveplan/api-auth-jwt — concrete JWT session resolver for @suaveplan/api-auth. Verifies a JWT presented on the Authorization header (or a configurable cookie) using @suaveplan/jws against either a JWKS endpoint (TTL + negative-cache + in-flight dedup) or a single static JsonWebKey; projects validated claims onto a Principal via an overridable mapper. Returns null on parse/verify failure (chain semantics) and contributes a Bearer JWT OpenAPI security scheme.
Stage-4 concrete SessionResolver for the
@suaveplan/api plugin system. Verifies a JWT
presented on the Authorization: Bearer <jwt> header (or a configured
cookie) against either a remote JWKS endpoint or a single static JWK,
then projects the validated claims onto the foundation's Principal
contract via an overridable mapper.
This is the adapter you pair with hosted identity providers (Clerk,
Auth0, Cognito, Stytch, custom Keycloak deployments) or with any
self-hosted JWT-issuing provider. It is session-resolver only —
login / register / refresh routes are the responsibility of an auth
provider, not this package.
Documentation tree
- claims-mapper — Default and runtime helpers for converting a verified JWT payload (
Claims) into aPrincipalfrom `@suaveplan/api-ty…- claims-mapper — Default and runtime helpers for converting a verified JWT payload (
Claims) into aPrincipalfrom `@suaveplan/api-ty…
- claims-mapper — Default and runtime helpers for converting a verified JWT payload (
- error-codes — Stable error-code registry for
@suaveplan/api-auth-jwt, exposing theAUTH_JWT.*namespace viadefineCodesfrom `@…- error-codes — Stable error-code registry for
@suaveplan/api-auth-jwt, exposing theAUTH_JWT.*namespace viadefineCodesfrom `@…
- error-codes — Stable error-code registry for
- jwks-cache — In-process JWKS cache for
@suaveplan/api-auth-jwt. Fetches a JWKS document from a remote endpoint, holds it under a p…- jwks-cache — In-process JWKS cache for
@suaveplan/api-auth-jwt. Fetches a JWKS document from a remote endpoint, holds it under a p…
- jwks-cache — In-process JWKS cache for
- options — Defines the Zod-validated boundary for
createJwtSessionResolverand the companionvalidateOptionshelper. The bound…- options — Defines the Zod-validated boundary for
createJwtSessionResolverand the companionvalidateOptionshelper. The bound…
- options — Defines the Zod-validated boundary for
- resolver — Stage-4 concrete
SessionResolverfactory for the API plugin system. Reads a JWT from the request (Authorization h…- resolver — Stage-4 concrete
SessionResolverfactory for the API plugin system. Reads a JWT from the request (Authorization h…
- resolver — Stage-4 concrete
- security-scheme — Builds the
SecuritySchemeContributionthis adapter contributes to the generated OpenAPI document. The shape is the ca…- security-scheme — Builds the
SecuritySchemeContributionthis adapter contributes to the generated OpenAPI document. The shape is the ca…
- security-scheme — Builds the
Surface
./resolver—createJwtSessionResolver(opts)../jwks-cache—JwksCachewith TTL, negative cache, in-flight dedup,kid-miss refresh../claims-mapper—defaultClaimsToPrincipal+runClaimsMapperhelpers../security-scheme—JWT_BEARER_SCHEMEandcreateJwtBearerSecurityScheme(name)for OpenAPI emission../error-codes—AUTH_JWT_*codesAuthJwtErrorclass.
./options— Zod-validated options boundary.
Quick start
import { createJwtSessionResolver } from "@suaveplan/api-auth-jwt/resolver";
import { JWT_BEARER_SCHEME } from "@suaveplan/api-auth-jwt/security-scheme";
const resolver = createJwtSessionResolver({
jwksUrl: "https://idp.example/.well-known/jwks.json",
issuer: "https://idp.example",
audience: "https://api.example",
algorithms: ["RS256"],
});
// Use in an api-host AuthAdapter:
const adapter = {
resolver,
securityScheme: JWT_BEARER_SCHEME,
};
Pairing with hosted IdPs
The package is designed to be paired with an external identity provider
that already issues JWTs. The recipe is the same for every provider —
plug in the provider's JWKS URL, issuer, and audience, then add a custom
claimsToPrincipal when the provider uses non-standard claim names.
Clerk
createJwtSessionResolver({
jwksUrl: "https://your-instance.clerk.accounts.dev/.well-known/jwks.json",
issuer: "https://your-instance.clerk.accounts.dev",
audience: "your-frontend-api",
algorithms: ["RS256"],
claimsToPrincipal: (claims) => {
const sub = claims["sub"];
if (typeof sub !== "string") return null;
return {
id: sub as never,
scopes: [] as never[],
tenantId: typeof claims["org_id"] === "string"
? (claims["org_id"] as never)
: undefined,
claims,
};
},
});
Auth0
createJwtSessionResolver({
jwksUrl: "https://your-tenant.auth0.com/.well-known/jwks.json",
issuer: "https://your-tenant.auth0.com/",
audience: "https://api.example.com",
algorithms: ["RS256"],
});
Cognito
createJwtSessionResolver({
jwksUrl: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX/.well-known/jwks.json",
issuer: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX",
audience: "your-cognito-app-client-id",
algorithms: ["RS256"],
});
Semantics
resolve() returns null on any per-request soft failure (missing
token, malformed token, bad signature, wrong issuer, wrong audience,
expired, not-yet-valid, no matching JWKS key). That collapse lets the
upstream SessionResolverChain fall through to the next adapter
(anonymous, static-bearer, etc.). It throws only on infrastructure
failures — AUTH_JWT.JWKS_FETCH_FAILED when the JWKS endpoint is
unreachable, AUTH_JWT.INVALID_KEY_FORMAT for a malformed static key,
AUTH_JWT.INVALID_CLAIMS_MAPPER when the caller's mapper throws or
returns a non-Principal value.
License
MIT — see the repository.