You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI中如何解码Authlib谷歌OAuth返回的JWT id_token

谷歌ID Token解码与校验实现方案

针对你的FastAPI+Authlib谷歌认证场景,不需要手动指定密钥,Authlib会自动对接谷歌的公钥服务完成ID Token的验证与解码,具体实现步骤如下:

核心逻辑说明

谷歌ID Token是遵循OpenID Connect标准的JWT,谷歌会通过公开的JWKS端点提供公钥用于验证签名。Authlib的OAuth客户端已经封装了自动获取公钥、验证签名与标准声明(过期时间、受众、发行者等)的逻辑,无需手动处理密钥管理。

具体代码实现

假设你已经完成谷歌OAuth客户端的初始化,以下是路由保护依赖函数的完整实现:

1. 初始化OAuth(已完成的部分可跳过)

from authlib.integrations.starlette_client import OAuth
from fastapi import FastAPI, Request, HTTPException, Depends
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()
# 注意:生产环境要使用安全的随机密钥
app.add_middleware(SessionMiddleware, secret_key="your-production-secret-key")

oauth = OAuth(app)
oauth.register(
    name='google',
    client_id='YOUR_GOOGLE_CLIENT_ID',
    client_secret='YOUR_GOOGLE_CLIENT_SECRET',
    # 使用谷歌的OpenID配置元数据,Authlib会自动获取JWKS等信息
    server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
    client_kwargs={
        'scope': 'openid email profile'
    }
)

2. 编写路由保护依赖

async def get_current_user(request: Request):
    # 从Cookie获取ID Token(根据你的前端传参方式调整,比如用Authorization头)
    id_token = request.cookies.get("id_token")
    if not id_token:
        raise HTTPException(status_code=401, detail="未提供认证Token")
    
    # 校验与Session中存储的Token一致性
    session_token = request.session.get("id_token")
    if id_token != session_token:
        raise HTTPException(status_code=401, detail="Token不匹配")
    
    try:
        # Authlib自动验证签名、过期时间、受众等,并解码出用户信息
        user_info = await oauth.google.verify_id_token(id_token)
    except Exception as e:
        raise HTTPException(status_code=401, detail=f"Token无效或已过期: {str(e)}")
    
    # (可选)手动二次校验过期时间(verify_id_token已自动处理,此步可省略)
    import time
    if user_info['exp'] < time.time():
        raise HTTPException(status_code=401, detail="Token已过期")
    
    return user_info

3. 保护路由使用示例

@app.get("/api/protected")
async def protected_resource(current_user=Depends(get_current_user)):
    return {
        "status": "success",
        "message": "访问受保护资源成功",
        "user": {
            "email": current_user.get("email"),
            "name": current_user.get("name"),
            "google_id": current_user.get("sub")
        }
    }

前端传参调整(可选)

如果你的前端不是通过Cookie传递Token,而是使用Authorization: Bearer <token>头,只需修改依赖中的Token获取逻辑:

auth_header = request.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
    raise HTTPException(status_code=401, detail="认证头格式错误")
id_token = auth_header.split(" ")[1]

关键注意事项

  • 必须使用server_metadata_url而非手动配置授权/Token端点,这样Authlib才能自动获取谷歌的JWKS公钥地址
  • verify_id_token会自动校验JWT的iss(发行者必须是谷歌)、aud(受众必须是你的客户端ID)、exp(过期时间)等核心声明,无需手动编写校验逻辑
  • 生产环境务必使用强随机的SessionMiddleware密钥,避免Session被伪造

内容的提问来源于stack exchange,提问作者Emiliano Acevedo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:50:09