Auth0 FastAPI API 集成
使用 auth0-fastapi-api 保护 FastAPI API 端点,通过 JWT 访问令牌验证。
注意:此 SDK 目前处于 beta 阶段,API 表面可能会在稳定 1.0 版本发布之前发生变化。请检查 PyPI 以获取最新版本。
要求 Python >= 3.9 和 FastAPI >= 0.115.11。
前提条件
FastAPI 应用程序(Python 3.9+)
Auth0 API 资源配置(不是应用程序 —— 必须是 API)
如果您尚未设置 Auth0,请先使用 auth0-quickstart 技能
何时不使用
服务器渲染的 Web 应用程序 —— 使用基于会话的登录/注销流程
单页应用程序 —— 使用 auth0-react、auth0-vue 或 auth0-angular 进行客户端身份验证
移动应用程序 —— 使用 auth0-react-native 或 auth0-android
颁发令牌 —— 此技能用于验证访问令牌,而不是颁发它们
快速入门工作流
pip install auth0-fastapi-api python-dotenv
您需要在 Auth0 中创建一个 API(不是应用程序)。
停止 —— 在继续之前询问用户。
询问用户:“您如何创建 Auth0 API 资源?
自动化 —— 我将运行 Auth0 CLI 脚本来创建资源并将确切的值写入您的 .env 文件。
手动 —— 您自己在 Auth0 仪表板中创建 API(或通过 auth0 apis create),并提供域和受众。
您更喜欢哪一个?(1 = 自动化 / 2 = 手动)”
不要在用户回答之前继续执行任何设置步骤。
不要默认为手动。
如果用户选择自动化,请按照设置指南完成 CLI 脚本。
自动化路径将为您编写 .env 文件 —— 跳过下面的步骤 3,直接转到步骤 4。
如果用户选择手动,请按照设置指南(手动设置部分)进行完整的说明。
然后继续执行下面的步骤 3。
手动 API 创建的快速参考:
# 使用 Auth0 CLI
auth0 apis create \
--name "My FastAPI API" \
--identifier https://my-api.example.com
或者在 Auth0 仪表板中手动创建:Applications -> APIs
创建 .env 文件:
AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_AUDIENCE=https://your-api.example.com
AUTH0_DOMAIN 是您的 Auth0 租户域(不包括 https://)。
AUTH0_AUDIENCE 是您在 Auth0 中创建 API 资源时设置的 API 标识符。
导入 os
从 fastapi 导入 FastAPI、Depends
从 fastapi_plugin 导入 Auth0FastAPI
从 dotenv 导入 load_dotenv
load_dotenv()
app = FastAPI()
auth0 = Auth0FastAPI(
domain=os.getenv("AUTH0_DOMAIN"),
audience=os.getenv("AUTH0_AUDIENCE"),
)
为每个应用程序创建一个 Auth0FastAPI 实例,并在路由中重用它。
永远不要硬编码域或受众 —— 始终使用环境变量。
# 需要任何有效的访问令牌
@app.get("/api/private")
async def private(claims: dict = Depends(auth0.require_auth())):
return {"user": claims["sub"]}
# 无需身份验证
@app.get("/api/public")
async def public():
return {"message": "Public endpoint"}
require_auth() 依赖项验证 Bearer 令牌,验证颁发者和受众,并返回解码的 JWT 声明。
错误响应:
400 invalid_request —— 缺少或格式错误的 Authorization 标头
401 invalid_token —— 过期令牌、无效签名、错误的颁发者/受众
403 insufficient_scope —— 有效令牌但缺少所需范围
500 internal_server_error —— 意外错误
响应体格式:{"detail": {"error": "...", "error_description": "..."}}
# 需要 read:messages 范围
@app.get("/api/messages")
async def get_messages(claims: dict = Depends(auth0.require_auth(scopes="read:messages"))):
return {"messages": []}
# 需要 read:data 和 write:data 范围
@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=...) 检查 JWT 中的范围声明。
所有指定的范围必须存在(AND 逻辑)。
缺少范围将返回 403。
依赖项直接返回解码的 JWT 声明:
@app.get("/api/profile")
async def profile(claims: dict = Depends(auth0.require_auth())):
return {
"sub": claims["sub"], # 用户 ID
"scope": claims.get("scope"), # 授予的范围
}
关键声明:
claims["sub"] —— 用户/客户端 ID
claims["scope"] —— 空格分隔的授予范围
claims["iss"] —— 颁发者(您的 Auth0 域 URL)
claims["aud"] —— 受众
claims["exp"] —— 过期时间戳
claims["iat"] —— 发布时间戳
@app.get("/api/protected", dependencies=[Depends(auth0.require_auth())])
async def protected():
return {"message": "您需要有效的访问令牌才能看到此内容。"}
# 无令牌 —— 预期 401
curl http://localhost:8000/api/private
# 有有效访问令牌
curl http://localhost:8000/api/private \
-H "Authorization: Bearer "