Hardening and operations#
Browser sessions require native CSRF coverage. Static security headers use
Litestar’s native response-header configuration and are backfilled onto every
response, including framework error responses. Use
SecurityHeadersConfig.hardened() as the recommended opt-in baseline for
HSTS, frame, content-type, and referrer protection; a handler that explicitly
sets a configured header keeps its value. Optional CSP has no guessed
allowlist: applications provide every directive. Static CSP adds no send hook;
nonce CSP generates at least 128 random bits per response and uses one native
before_send hook. Report-only mode emits the standard report-only header.
No CSP report collector is included.
auth=public() excludes a stateless route from native CSRF. Public handlers
that establish cookie-authenticated state must instead declare
csrf_required=True. Conversely, auth=exclude() bypasses authentication
only: session-capable excluded routes retain their derived CSRF coverage.
Pin issuer, audience, algorithms, redirect URIs, discovery origins, JWKS URLs, network egress, and IAP ingress. JWKS fresh hits are lock-free; misses use single-flight refresh, bounded documents, negative caching, stale policy, and explicit sync-worker normalization. Keep retired verification keys through the maximum issued-token lifetime.
Store private keys, peppers, OAuth client secrets, session secrets, and attestation roots in application secret management. Never log raw credentials, nonces, refresh tokens, API keys, recovery codes, passkey challenges, or MFA login challenges. Use shared atomic rate-limit, revocation, and MFA-login challenge stores across workers and monitor verification-unavailable outcomes.
MFA and OAuth transaction protectors also use application-owned AES-256-GCM
key material. Load each exact 32-byte key from a KMS or secret store rather
than placing it in source code. Construct AESGCMSecretProtector for
MFAConfig.secret_protector and AESGCMOAuthTransactionProtector for the
OAuth transaction store and token vault. Rotate without invalidating still-live
envelopes: add the former active SecretProtectorKey or
OAuthTransactionProtectorKey to retained_keys before promoting a new
active_key. An application-owned replacement can be checked with
assert_secret_protector_conformance() or
assert_oauth_transaction_protector_conformance().
Before enabling MFAConfig.require_at_login in a deployment, enroll a viable
factor for every affected account and verify the completion routes with the
same CSRF and session middleware used in production. The MFA-login challenge
store must atomically burn a revealed challenge; a process-local implementation
is suitable only for a single worker. Treat the reveal-once challenge and the
completion proof like passwords: keep both out of application, proxy, and
audit logs.