Skip to content

ASGI Adapter

The ASGI adapter protects any Python ASGI application - FastAPI, Starlette, Quart, Django ASGI - with fail-closed Caracal mandate verification. It is pure ASGI: it imports no web framework and delegates every check to Verify Package.

CaracalASGIAuth is the only public package entry point. Use it for inbound ASGI HTTP or WebSocket authentication, not outbound SDK calls.

Terminal window
pip install caracalai-asgi
from caracalai_asgi import CaracalASGIAuth
from caracalai_revocation import InMemoryRevocationStore
from fastapi import FastAPI
app = FastAPI()
app.add_middleware(
CaracalASGIAuth,
audience="resource://pipernet",
revocations=InMemoryRevocationStore(),
required_scopes=["pipernet:read"],
routes={
"/payouts": {"required_scopes": ["pipernet:payout"], "require_delegation": True},
},
exclude=["/healthz"],
)
@app.get("/balances")
async def balances(request):
principal = request.state.caracal
return {"sub": principal.sub, "scopes": principal.scope}

issuer defaults to CARACAL_STS_URL and expected_zone_id to CARACAL_ZONE_ID, so a provider deployed with the standard Caracal workload variables only states its own audience and revocation store. Construction fails if no issuer or zone can be resolved.

OptionUse it for
audienceThe provider’s own resource identifier; mandates minted for other resources are rejected.
revocationsRevocation store consulted on every request. Use Redis Revocation Store in production.
required_scopes / required_targetsDefault scope and target requirements for every route.
require_session / require_delegation / max_hop_countSession identity, delegated authority, and Delegation-depth requirements.
routesPer-route overrides by path prefix; the longest matching prefix wins. Any option above can be overridden.
excludePath prefixes served without verification (health and readiness probes).

required_use defaults to resource; require_session and require_delegation default to false. Exclusions and route prefixes match path-segment boundaries, and the longest route prefix wins.

  • Verified claims are stored as scope["state"]["caracal"], surfaced as request.state.caracal in Starlette and FastAPI.
  • Failed verification answers with the shared status mapping (http_status_for_auth_error): 401 for credential failures, 403 for insufficient authority, with the standard error/error_description JSON body.
  • WebSocket connections that fail verification are closed with policy code 1008; lifespan events pass through.
  • Call await middleware.warmup() at startup to prefetch the zone JWKS before the first request.

The adapter verifies inbound mandates; it does not create Sessions or Delegations. Use the Python SDK to create Caracal context before making outbound calls.