基于AWS Fargate+ALB+Cognito的FastAPI OAuth2.0实现:API程序化访问问题
解决ALB集成Cognito后机器对机器调用的认证问题
问题根源
ALB与Cognito的默认集成是为浏览器端会话设计的:通过重定向到Cognito登录页完成认证,生成AWSELBAuthSessionCookie-0/1会话Cookie维持认证状态。但这种模式不会自动解析Authorization: Bearer {token}请求头,所以程序化调用时会被强制重定向到登录页。
可行解决方案
方案1:用Lambda自定义认证让ALB支持Bearer Token验证
保留ALB作为认证入口,同时适配机器对机器的Token验证场景:
- 创建Lambda函数,实现核心逻辑:
- 解析请求头中的
Authorization字段,提取Bearer Token。 - 调用Cognito的
GetUserAPI或通过JWKS公钥验证Token的签名、有效期、受众(Audience)和签发者(Issuer)。 - 验证通过则返回允许访问的IAM策略;验证失败返回401未授权。
- 解析请求头中的
- 在ALB的认证规则中,将默认的Cognito认证替换为自定义Lambda函数。
- 机器对机器客户端通过Cognito的Client Credentials流获取Access Token,请求时携带
Authorization: Bearer {token},ALB会调用Lambda完成Token验证,通过后放行请求到FastAPI。
方案2:关闭ALB认证,让FastAPI直接处理OAuth2.0验证
将认证逻辑下移到FastAPI,ALB仅承担负载均衡功能:
- 关闭ALB上的Cognito认证配置。
- 在FastAPI中集成OAuth2.0验证:
- 使用
OAuth2PasswordBearer类指定Cognito令牌端点。 - 通过Cognito的JWKS端点获取公钥,验证Token签名有效性。
- 示例代码片段:
from fastapi import FastAPI, Depends, HTTPException from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt COGNITO_JWKS_URL = "https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json" OAUTH2_SCHEME = OAuth2PasswordBearer(tokenUrl="https://{cognito_domain}/oauth2/token") app = FastAPI() async def verify_token(token: str = Depends(OAUTH2_SCHEME)): try: payload = jwt.decode( token, COGNITO_JWKS_URL, audience="{your_client_id}", issuer="{your_cognito_issuer_url}" ) return payload except JWTError: raise HTTPException(status_code=401, detail="无效的Token") @app.get("/api/protected") async def protected_route(payload: dict = Depends(verify_token)): return {"message": "访问成功", "auth_info": payload}
- 使用
- 客户端通过Client Credentials流获取Token后,携带
Authorization: Bearer {token}请求FastAPI接口即可。
方案3:程序化获取ALB会话Cookie(适配现有ALB认证配置)
如果必须保留ALB的Cookie认证模式,可通过程序模拟浏览器流程获取会话Cookie:
- 执行OAuth2.0 Authorization Code流:
- 构造Cognito授权URL:
https://{cognito_domain}/oauth2/authorize?client_id={client_id}&response_type=code&redirect_uri={redirect_uri}&scope=openid - 用HTTP客户端发送GET请求,处理重定向到Cognito登录页,提交用户名密码获取授权码(code)。
- 用授权码调用Cognito令牌端点
https://{cognito_domain}/oauth2/token,获取ID Token和Access Token。
- 构造Cognito授权URL:
- 向ALB发送测试请求,携带ID Token,ALB会生成
AWSELBAuthSessionCookie-0/1并返回。 - 后续API请求中,在
Cookie请求头中携带这两个Cookie,ALB会识别为已认证会话,放行请求。
关键注意事项
- 机器对机器场景优先使用Client Credentials流,无需用户交互,适合服务间调用。
- 验证Token时必须校验
aud(Cognito客户端ID)和iss(Cognito用户池URL),避免无效Token被放行。 - ALB会话Cookie有过期时间,需定期刷新或设置合理的过期时长。
内容的提问来源于stack exchange,提问作者Yehor Anisimov
相关产品推荐
相关产品推荐

