{"skill":{"slug":"auth0-fastapi-api","displayName":"Auth0 Fastapi Api","summary":"Use when securing FastAPI API endpoints with JWT Bearer token validation, scope/permission checks, or stateless auth - integrates auth0-fastapi-api for REST...","description":"---\nname: auth0-fastapi-api\ndescription: \"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.\"\nlicense: Apache-2.0\nmetadata:\n  author: Auth0 <support@auth0.com>\n  version: '1.0.1'\n  openclaw:\n    emoji: \"\\U0001F510\"\n    homepage: https://github.com/auth0/agent-skills\n---\n\n# Auth0 FastAPI API Integration\n\nProtect FastAPI API endpoints with JWT access token validation using `auth0-fastapi-api`.\n\n> **Note:** This SDK is currently in beta. The API surface may change before the stable 1.0 release. Check [PyPI](https://pypi.org/project/auth0-fastapi-api/) for the latest version. Requires Python >= 3.9 and FastAPI >= 0.115.11.\n\n---\n\n## Prerequisites\n\n- FastAPI application (Python 3.9+)\n- Auth0 API resource configured (not an Application — must be an API)\n- If you don't have Auth0 set up yet, use the `auth0-quickstart` skill first\n\n## When NOT to Use\n\n- **Server-rendered web applications** — Use a session-based login/logout flow instead\n- **Single Page Applications** — Use `auth0-react`, `auth0-vue`, or `auth0-angular` for client-side auth\n- **Mobile applications** — Use `auth0-react-native` or `auth0-android`\n- **Issuing tokens** — This skill is for *validating* access tokens, not issuing them\n\n---\n\n## Quick Start Workflow\n\n### 1. Install SDK\n\n```bash\npip install auth0-fastapi-api python-dotenv\n```\n\n### 2. Create Auth0 API\n\nYou need an **API** (not Application) in Auth0.\n\n> **STOP — ask the user before proceeding.**\n>\n> Ask exactly this question and wait for their answer before doing anything else:\n>\n> > \"How would you like to create the Auth0 API resource?\n> > 1. **Automated** — I'll run Auth0 CLI scripts that create the resource and write the exact values to your `.env` automatically.\n> > 2. **Manual** — You create the API yourself in the Auth0 Dashboard (or via `auth0 apis create`) and provide me the Domain and Audience.\n> >\n> > Which do you prefer? (1 = Automated / 2 = Manual)\"\n>\n> Do NOT proceed to any setup steps until the user has answered. Do NOT default to manual.\n\n**If the user chose Automated**, follow the [Setup Guide](references/setup.md) for complete CLI scripts. The automated path writes `.env` for you — skip Step 3 below and proceed directly to Step 4.\n\n**If the user chose Manual**, follow the [Setup Guide](references/setup.md) (Manual Setup section) for full instructions. Then continue with Step 3 below.\n\nQuick reference for manual API creation:\n\n```bash\n# Using Auth0 CLI\nauth0 apis create \\\n  --name \"My FastAPI API\" \\\n  --identifier https://my-api.example.com\n```\n\nOr create manually in Auth0 Dashboard → Applications → APIs\n\n### 3. Configure Environment\n\nCreate `.env`:\n\n```bash\nAUTH0_DOMAIN=your-tenant.us.auth0.com\nAUTH0_AUDIENCE=https://your-api.example.com\n```\n\n`AUTH0_DOMAIN` is your Auth0 tenant domain (without `https://`). `AUTH0_AUDIENCE` is the API identifier you set when creating the API resource in Auth0.\n\n### 4. Initialize Auth0\n\n```python\nimport os\nfrom fastapi import FastAPI, Depends\nfrom fastapi_plugin import Auth0FastAPI\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\napp = FastAPI()\n\nauth0 = Auth0FastAPI(\n    domain=os.getenv(\"AUTH0_DOMAIN\"),\n    audience=os.getenv(\"AUTH0_AUDIENCE\"),\n)\n```\n\nCreate one `Auth0FastAPI` instance per application and reuse it across routes. Never hardcode the domain or audience — always use environment variables.\n\n### 5. Protect Routes\n\n```python\n# Require any valid access token\n@app.get(\"/api/private\")\nasync def private(claims: dict = Depends(auth0.require_auth())):\n    return {\"user\": claims[\"sub\"]}\n\n# No authentication required\n@app.get(\"/api/public\")\nasync def public():\n    return {\"message\": \"Public endpoint\"}\n```\n\nThe `require_auth()` dependency validates the Bearer token, verifies the issuer and audience, and returns the decoded JWT claims.\n\nError responses:\n- **400** `invalid_request` — Missing or malformed Authorization header\n- **401** `invalid_token` — Expired token, invalid signature, wrong issuer/audience\n- **403** `insufficient_scope` — Valid token but missing required scopes\n- **500** `internal_server_error` — Unexpected errors\n\nResponse body format: `{\"detail\": {\"error\": \"...\", \"error_description\": \"...\"}}`\n\n### 6. Protect Routes with Scope Checks\n\n```python\n# Requires the read:messages scope\n@app.get(\"/api/messages\")\nasync def get_messages(claims: dict = Depends(auth0.require_auth(scopes=\"read:messages\"))):\n    return {\"messages\": []}\n\n# Requires both read:data and write:data scopes\n@app.post(\"/api/data\")\nasync def write_data(claims: dict = Depends(auth0.require_auth(scopes=[\"read:data\", \"write:data\"]))):\n    return {\"created\": True}\n```\n\n`require_auth(scopes=...)` checks the `scope` claim in the JWT. All specified scopes must be present (AND logic). Missing scopes return **403**.\n\n### 7. Access Token Claims\n\nThe decoded JWT claims are returned directly from the dependency:\n\n```python\n@app.get(\"/api/profile\")\nasync def profile(claims: dict = Depends(auth0.require_auth())):\n    return {\n        \"sub\": claims[\"sub\"],       # user ID\n        \"scope\": claims.get(\"scope\"),  # granted scopes\n    }\n```\n\nKey claims:\n- `claims[\"sub\"]` — user/client ID\n- `claims[\"scope\"]` — space-separated granted scopes\n- `claims[\"iss\"]` — issuer (your Auth0 domain URL)\n- `claims[\"aud\"]` — audience\n- `claims[\"exp\"]` — expiration timestamp\n- `claims[\"iat\"]` — issued-at timestamp\n\n### 8. Protect Routes Without Needing Claims\n\n```python\n@app.get(\"/api/protected\", dependencies=[Depends(auth0.require_auth())])\nasync def protected():\n    return {\"message\": \"You need a valid access token to see this.\"}\n```\n\n### 9. Test the API\n\n```bash\n# No token — expect 401\ncurl http://localhost:8000/api/private\n\n# With a valid access token\ncurl http://localhost:8000/api/private \\\n  -H \"Authorization: Bearer YOUR_ACCESS_TOKEN\"\n```\n\nGet a test token via Client Credentials flow or Auth0 Dashboard → APIs → Test tab.\n\n---\n\n## Common Mistakes\n\n| Mistake | Fix |\n|---------|-----|\n| Hardcoding `domain` or `audience` in source | Always read from environment variables — never embed credentials in code |\n| Using `python-jose` or `PyJWT` directly | Not needed; `auth0-fastapi-api` handles all validation via JWKS |\n| Manually parsing `Authorization` header | The SDK extracts and validates the token automatically |\n| Calling `jwt.decode()` manually | The SDK verifies tokens against the JWKS endpoint — do not verify yourself |\n| Using `fastapi-users` for Auth0 JWT validation | That package is for user management, not Auth0 JWT verification |\n| 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 |\n| Passing `domain` as full URL with `https://` | `domain` should be the bare domain, e.g. `my-tenant.us.auth0.com`, not `https://my-tenant.us.auth0.com` |\n| 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 |\n| Not configuring CORS for SPA clients | Add `CORSMiddleware` to allow requests from your frontend origin |\n| `os.getenv()` returns `None` silently | Ensure `python-dotenv` is installed and `load_dotenv()` is called before `Auth0FastAPI()` initialization — or use `os.environ[]` to fail fast |\n\n---\n\n## DPoP Support\n\nBuilt-in proof-of-possession token binding per RFC 9449. DPoP is enabled by default in mixed mode (accepts both Bearer and DPoP tokens). See [Integration Guide](references/integration.md#dpop-support) for configuration.\n\n---\n\n## Related Skills\n\n- `auth0-quickstart` - Basic Auth0 setup and framework detection\n- `auth0-mfa` - Add Multi-Factor Authentication\n- `auth0-cli` - Manage Auth0 resources from the terminal\n\n---\n\n## Quick Reference\n\n**Auth0FastAPI configuration:**\n```python\nauth0 = Auth0FastAPI(\n    domain=os.getenv(\"AUTH0_DOMAIN\"),       # required (or use domains)\n    audience=os.getenv(\"AUTH0_AUDIENCE\"),    # required\n    dpop_enabled=True,                       # default; set False for Bearer-only\n    dpop_required=False,                     # default; set True to reject Bearer tokens\n)\n```\n\n**Route protection:**\n```python\nDepends(auth0.require_auth())                    # any valid token\nDepends(auth0.require_auth(scopes=\"read:res\"))   # single scope\nDepends(auth0.require_auth(scopes=[\"r\", \"w\"]))   # all scopes required\n```\n\n**Accessing claims:**\n```python\nclaims[\"sub\"]           # user/client ID\nclaims[\"scope\"]         # space-separated scopes\n```\n\n**Environment variables:**\n- `AUTH0_DOMAIN` — your Auth0 tenant domain (e.g. `tenant.us.auth0.com`)\n- `AUTH0_AUDIENCE` — your API identifier (e.g. `https://api.example.com`)\n\n**Common Use Cases:**\n- Protect routes → `Depends(auth0.require_auth())` (see Step 5)\n- Scope enforcement → `Depends(auth0.require_auth(scopes=\"...\"))` (see Step 6)\n- DPoP token binding → [Integration Guide](references/integration.md#dpop-support)\n- Reverse proxy setup → [Integration Guide](references/integration.md#reverse-proxy-support)\n- Advanced configuration → [API Reference](references/api.md)\n\n---\n\n## Detailed Documentation\n\n- **[Setup Guide](references/setup.md)** — Auth0 CLI setup, environment configuration, getting test tokens\n- **[Integration Guide](references/integration.md)** — DPoP, scopes, error handling, reverse proxy, testing\n- **[API Reference](references/api.md)** — Complete constructor options, method signatures, error codes\n\n---\n\n## References\n\n- [auth0-fastapi-api GitHub](https://github.com/auth0/auth0-fastapi-api)\n- [auth0-fastapi-api on PyPI](https://pypi.org/project/auth0-fastapi-api/)\n- [Auth0 FastAPI API Quickstart](https://auth0.com/docs/quickstart/backend/fastapi)\n- [FastAPI Dependency Injection](https://fastapi.tiangolo.com/tutorial/dependencies/)\n- [Access Tokens Guide](https://auth0.com/docs/secure/tokens/access-tokens)\n","tags":{"latest":"1.0.1"},"stats":{"comments":0,"downloads":350,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1778072337203,"updatedAt":1778492859420},"latestVersion":{"version":"1.0.1","createdAt":1778072337203,"changelog":"Initial publish","license":"MIT-0"},"metadata":{"setup":[],"os":null,"systems":null},"owner":{"handle":"auth0","userId":"s1705618g3dhya8px0x9gnyy4d84geyh","displayName":"Auth0","image":"https://avatars.githubusercontent.com/u/2824157"},"moderation":null}