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.
Prerequisites
Section titled “Prerequisites”- A Caracal-mandate resource whose audience is
resource://pipernetor another stable resource ID. - STS issuer and zone configuration plus a shared production revocation store.
- Public health paths identified before middleware is enabled.
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://pipernet", revocations=InMemoryRevocationStore(), required_scopes=["pipernet:read"], routes={ "/payouts": {"required_scopes": ["pipernet:payout"], "require_delegation": True}, }, exclude=["/healthz"],)
@app.post("/payouts/create")async def create_payout(request: Request): principal = request.state.caracal return {"subject": principal.sub}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_session | Require a governed Session. |
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.
Expected result: missing or invalid credentials return 401, valid but insufficient authority returns 403, excluded probes remain reachable, and handlers receive request.state.caracal only after verification.
For every middleware field, use ASGI Adapter reference.
Next Step
Section titled “Next Step”Replace the in-memory store with the Redis backend and run the revocation case in Test Caracal Integrations.

