from fastapi_oauth20 import FastAPIOAuth20
使用指南¶
本指南介绍如何将 FastAPI OAuth2.0 库与各种 OAuth2 提供程序一起使用。
基本用法¶
1. 选择 OAuth2 提供商并初始化客户端¶
from fastapi_oauth20 import GitHubOAuth20, GoogleOAuth20, FastAPIOAuth20
from fastapi import FastAPI, Depends
from fastapi.responses import RedirectResponse
import secrets
app = FastAPI()
# 初始化 GitHub OAuth2 客户端
github_client = GitHubOAuth20(
client_id="your_github_client_id",
client_secret="your_github_client_secret"
)
2. 创建 FastAPI OAuth2 依赖¶
# 创建 FastAPI OAuth2 依赖
github_oauth = FastAPIOAuth20(
client=github_client,
redirect_uri="http://localhost:8000/auth/github/callback"
)
3. 定义授权端点¶
@app.get("/oauth2/github")
async def oauth2_github():
"""重定向用户到 OAuth2 提供商进行授权"""
# 生成安全的 state 参数用于 CSRF 保护
state = secrets.token_urlsafe(32)
auth_url = await github_client.get_authorization_url(
redirect_uri="http://localhost:8000/auth/github/callback",
state=state
)
return RedirectResponse(url=auth_url)
4. 处理 OAuth 回调¶
@app.get("/oauth2/github/callback")
async def oauth2_github_callback(
oauth_result: Annotated[FastAPIOAuth20, Depends(github_oauth)]
):
"""处理 GitHub OAuth 回调"""
token_data, state = oauth_result
# 获取用户信息
user_info = await github_client.get_userinfo(token_data["access_token"])
return {
"user": user_info,
"access_token": token_data["access_token"],
"state": state
}
令牌刷新¶
某些提供商支持刷新令牌来延长会话:
@app.post("/oauth2/refresh")
async def oauth2_refresh_token(refresh_token: str):
"""使用刷新令牌获取新的访问令牌"""
try:
new_tokens = await google_client.refresh_token(refresh_token)
return {"access_token": new_tokens["access_token"]}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
令牌撤销¶
用户登出时撤销令牌:
@app.post("/oauth2/revoke")
async def oauth2_revoke_token(access_token: str):
"""撤销访问令牌"""
try:
await google_client.revoke_token(access_token)
return {"message": "令牌撤销成功"}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
错误处理¶
如果回调逻辑内部发生错误(用户拒绝访问、授权代码无效......),依赖关系将引发 OAuth20AuthorizeCallbackError 错误
它继承自 FastAPI 的 HTTPException,因此默认的
FastAPI 异常处理程序会自动对其进行处理。您可以通过为 OAuth20AuthorizeCallbackError 实现自己的异常处理程序来自定义此行为
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi_oauth20 import OAuth20AuthorizeCallbackError
app = FastAPI()
@app.exception_handler(OAuth20AuthorizeCallbackError)
async def oauth2_authorize_callback_error_handler(request: Request, exc: OAuth20AuthorizeCallbackError):
detail = exc.detail
status_code = exc.status_code
return JSONResponse(
status_code=status_code,
content={"message": "The OAuth2 callback failed", "detail": detail},
)
完整示例¶
from typing import Annotated
from fastapi import FastAPI, Depends, HTTPException
from fastapi.responses import RedirectResponse
from fastapi_oauth20 import GitHubOAuth20, FastAPIOAuth20
from fastapi_oauth20 import OAuth20AuthorizeCallbackError
import secrets
app = FastAPI()
# 初始化客户端
github_client = GitHubOAuth20(
client_id="your_client_id",
client_secret="your_client_secret"
)
# 创建依赖
github_oauth = FastAPIOAuth20(
client=github_client,
redirect_uri="http://localhost:8000/auth/github/callback"
)
@app.get("/oauth2/github")
async def oauth2_github():
"""GitHub 授权入口"""
state = secrets.token_urlsafe(32)
auth_url = await github_client.get_authorization_url(
redirect_uri="http://localhost:8000/auth/github/callback",
state=state
)
return RedirectResponse(url=auth_url)
@app.get("/oauth2/github/callback")
async def oauth2_github_callback(
oauth_result: Annotated[FastAPIOAuth20, Depends(github_oauth)]
):
"""GitHub 授权回调"""
token_data, state = oauth_result
user_info = await github_client.get_userinfo(token_data["access_token"])
return {"user": user_info}
# 错误处理
@app.exception_handler(OAuth20AuthorizeCallbackError)
async def oauth_error_handler(request, exc):
return {"error": "授权失败", "detail": exc.detail}
注意事项¶
- 安全性: 始终使用 HTTPS 端点
- 状态管理: 使用安全的 state 参数防止 CSRF 攻击
- 令牌存储: 安全地存储访问令牌和刷新令牌
- 错误处理: 妥善处理各种 OAuth2 错误场景
- 作用域: 只请求必要的作用域,遵循最小权限原则