Auth
Inbound authentication, tenant derivation, and isolation defenses. Source: felix.auth in felix-run/felix.
Modes
FELIX_AUTH_MODE:
| Mode | Behavior |
|---|---|
none |
Anonymous principal (tenant_id=default). Requires FELIX_ALLOW_INSECURE=true outside development when binding a non-loopback host |
api_key |
`Authorization: Bearer |
jwt |
Bearer JWT verified via FELIX_JWT_VERIFIERS + JWKS (FELIX_JWKS_PUBLIC for self-issued) |
Public paths stay open in all modes: /health, /metrics, /docs, /openapi.json, /redoc, /.well-known/*.
Missing credentials in api_key / jwt → 401 (fail closed). Mint self-issued tokens with felix mint-jwt.
Manifest gates
Routes call enforce_inbound_auth (via prepare_tenant_invoke):
inbound.allow_anonymous: false→ reject anonymousinbound.required_scopes→ all must be present on the principal → else 403
Management routes use require_scope (audit:read, manifests:write, approvals:decide, …).
RequestContext
Auth middleware installs a contextvars-backed RequestContext: settings, principal (tenant / scopes / subject), and a fresh LimitState. Tool wrappers and patterns read it via get_context() / try_get_context() — no parameter threading, harder to tamper.
Tenant derivation (JWT)
custom:tenant_idclaimtenant_idclaim- First label of issuer host
- Else
default(also used for anonymous / api_key default meta)
Internal consumers
POST /internal/* is self-authenticating: shared secret header (FELIX_CONSUMER_SHARED_SECRET / X-Felix-Consumer-Secret) with constant-time compare. Required when auth_mode ≠ none (and in production).
Thread-id smuggling
Caller-supplied thread suffixes (body.thread_id, x-thread-id) reject : and #. The server always prefixes {tenant_id}:.
Outbound
Manifest MCP / peer / container auth refs resolve outbound headers (bearer literals or OAuth client-credentials). Tokens may be cached encrypted at rest when FELIX_OAUTH_CACHE_KEY is set. Outbound hosts pass SSRF allow-list checks before a bearer is attached.
Local Compose defaults to FELIX_AUTH_MODE=none + FELIX_ALLOW_INSECURE=true. Production: prefer jwt or api_key and keep ALLOW_INSECURE false — see deploy.