Protect a FastAPI App
Use caracalai-asgi when a FastAPI, Starlette, or other ASGI app should verify Caracal mandates before request handlers run. This is the provider-side boundary: a partner serving Caracal-governed customers verifies each inbound mandate against the zone’s keys before doing any work.
Install
Section titled “Install”pip install caracalai-asgi caracalai-revocationUse a Redis-backed revocation store in production. The in-memory store is only suitable for local development and tests.
Add middleware
Section titled “Add middleware”from caracalai_asgi import CaracalASGIAuthfrom caracalai_revocation import InMemoryRevocationStorefrom fastapi import FastAPI, Request
app = FastAPI()app.add_middleware( CaracalASGIAuth, audience="resource://billing-api", revocations=InMemoryRevocationStore(), required_scopes=["billing:read"], routes={ "/payouts": {"required_scopes": ["billing:payout"], "require_delegation": True}, }, exclude=["/healthz"],)
@app.post("/payouts/create")async def create_payout(request: Request): principal = request.state.caracal return {"actor": principal.sub, "agent": principal.agent_session_id}With CARACAL_STS_URL and CARACAL_ZONE_ID set — the standard Caracal workload variables — the middleware resolves the issuer and zone itself; you state only your own audience and revocation store. Requests reach your handlers only after the mandate’s signature, issuer, audience, zone, token use, scopes, and revocation anchors all verify.
Enforce the right boundary
Section titled “Enforce the right boundary”| Option | Use it for |
|---|---|
required_scopes | Route-level scope checks. |
required_targets | Resource-target checks. |
require_agent | Reject non-agent mandates. |
require_delegation | Require delegated authority. |
max_hop_count | Limit delegation depth. |
routes | Apply any of the above per path prefix; the longest matching prefix wins. |
Validate
Section titled “Validate”- Exchange for a mandate that targets the resource.
- Call the protected route with
Authorization: Bearer <mandate>. - Remove a required scope and confirm the route returns
403. - Revoke the session and confirm the route rejects the old mandate.
Related pages: Mandates and Sessions and Revocation.

