Loading...
Loading...
Use when securing FastAPI API endpoints with JWT Bearer token validation, scope/permission checks, or stateless auth - integrates auth0-fastapi-api for REST APIs receiving access tokens from SPAs, mobile apps, or other clients. Also handles DPoP proof-of-possession token binding. Triggers on: Auth0FastAPI, FastAPI API auth, JWT validation, require_auth, DPoP.
npx skill4agent add auth0/agent-skills auth0-fastapi-apiauth0-fastapi-apiNote: This SDK is currently in beta. The API surface may change before the stable 1.0 release. Check PyPI for the latest version. Requires Python >= 3.9 and FastAPI >= 0.115.11.
auth0-quickstartauth0-reactauth0-vueauth0-angularauth0-react-nativeauth0-androidpip install auth0-fastapi-api python-dotenvSTOP — ask the user before proceeding.Ask exactly this question and wait for their answer before doing anything else:"How would you like to create the Auth0 API resource?
- Automated — I'll run Auth0 CLI scripts that create the resource and write the exact values to your
automatically..env- Manual — You create the API yourself in the Auth0 Dashboard (or via
) and provide me the Domain and Audience.auth0 apis createWhich do you prefer? (1 = Automated / 2 = Manual)"Do NOT proceed to any setup steps until the user has answered. Do NOT default to manual.
.env# Using Auth0 CLI
auth0 apis create \
--name "My FastAPI API" \
--identifier https://my-api.example.com.envAUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_AUDIENCE=https://your-api.example.comAUTH0_DOMAINhttps://AUTH0_AUDIENCEimport os
from fastapi import FastAPI, Depends
from auth0_fastapi_api import Auth0FastAPI
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
auth0 = Auth0FastAPI(
domain=os.getenv("AUTH0_DOMAIN"),
audience=os.getenv("AUTH0_AUDIENCE"),
)Auth0FastAPI# Require any valid access token
@app.get("/api/private")
async def private(claims: dict = Depends(auth0.require_auth())):
return {"user": claims["sub"]}
# No authentication required
@app.get("/api/public")
async def public():
return {"message": "Public endpoint"}require_auth()invalid_requestinvalid_tokeninsufficient_scopeinternal_server_error{"detail": {"error": "...", "error_description": "..."}}# Requires the read:messages scope
@app.get("/api/messages")
async def get_messages(claims: dict = Depends(auth0.require_auth(scopes="read:messages"))):
return {"messages": []}
# Requires both read:data and write:data scopes
@app.post("/api/data")
async def write_data(claims: dict = Depends(auth0.require_auth(scopes=["read:data", "write:data"]))):
return {"created": True}require_auth(scopes=...)scope@app.get("/api/profile")
async def profile(claims: dict = Depends(auth0.require_auth())):
return {
"sub": claims["sub"], # user ID
"scope": claims.get("scope"), # granted scopes
}claims["sub"]claims["scope"]claims["iss"]claims["aud"]claims["exp"]claims["iat"]@app.get("/api/protected", dependencies=[Depends(auth0.require_auth())])
async def protected():
return {"message": "You need a valid access token to see this."}# No token — expect 401
curl http://localhost:8000/api/private
# With a valid access token
curl http://localhost:8000/api/private \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"| Mistake | Fix |
|---|---|
Hardcoding | Always read from environment variables — never embed credentials in code |
Using | Not needed; |
Manually parsing | The SDK extracts and validates the token automatically |
Calling | The SDK verifies tokens against the JWKS endpoint — do not verify yourself |
Using | That package is for user management, not Auth0 JWT verification |
| Created an Application instead of an API in Auth0 | Must create an API resource (Applications → APIs) — an Application doesn't issue access tokens with the right audience |
Passing | |
| Using an ID token instead of an access token | Must use the access token for API auth — ID tokens are for the client app, not for API authorization |
| Not configuring CORS for SPA clients | Add |
| Ensure |
auth0-quickstartauth0-mfaauth0 = Auth0FastAPI(
domain=os.getenv("AUTH0_DOMAIN"), # required (or use domains)
audience=os.getenv("AUTH0_AUDIENCE"), # required
dpop_enabled=True, # default; set False for Bearer-only
dpop_required=False, # default; set True to reject Bearer tokens
)Depends(auth0.require_auth()) # any valid token
Depends(auth0.require_auth(scopes="read:res")) # single scope
Depends(auth0.require_auth(scopes=["r", "w"])) # all scopes requiredclaims["sub"] # user/client ID
claims["scope"] # space-separated scopesAUTH0_DOMAINtenant.us.auth0.comAUTH0_AUDIENCEhttps://api.example.comDepends(auth0.require_auth())Depends(auth0.require_auth(scopes="..."))