Python实现AWS Cognito OAuth令牌自动获取及403问题排查
问题分析与解决方案
问题背景
应用采用AWS Cognito OAuth授权码模式,Postman配置以下信息后可正常获取令牌并调用接口:
Grant Type: Authorization code Callback URL: https://abcd.com/callback Auth URL: https://appid.auth.us-east-2.amazoncognito.com/oauth2/authorize Access Token URL: https://appid.auth.us-east-2.amazoncognito.com/oauth2/token Client ID: abcdeftlh2n95llrfsjq2q Client Secret: None Scope: openid profile user/*.* Client Authentication: send client credentials in the body
自动化测试时遇到两个问题:
- 直接用
requests/rauth向令牌URL发GET请求传用户名密码,返回Invalid Request - 用
boto3获取IdToken后调用接口返回403,替换为Postman获取的令牌则正常返回200
问题1:requests/rauth调用失败原因
授权码模式(Authorization Code Grant)的正确流程是两步走:
- 先跳转到Cognito授权页面,用户登录后拿到授权码(
code) - 再用授权码、客户端ID等参数向令牌URL发POST请求,换取访问令牌
你直接传用户名密码到令牌URL,不符合授权码模式的要求,所以返回无效请求。如果想跳过浏览器跳转做自动化,可改用密码模式(Password Grant),但前提是你的Cognito用户池客户端已开启该授权类型。
问题2:boto3获取的令牌导致403的原因
你用boto3的initiate_auth调用USER_PASSWORD_AUTH流程拿到的是IdToken,但接口需要的是Access Token,同时存在两个关键问题:
- 令牌格式错误:请求头需添加
Bearer前缀,接口才能正确识别令牌类型 - 令牌类型不符:
IdToken用于身份认证,而资源访问需要Access Token,需在认证时指定匹配的scope
修正后的boto3代码
import boto3 import requests username = "blabla" password = "Password123!" client_id = "abcdef4q01tlh2n95llrfsjq2q" region = "us-east-2" # 初始化Cognito客户端 provider_client = boto3.client('cognito-idp', region_name=region) # 发起认证,指定scope获取Access Token resp = provider_client.initiate_auth( AuthFlow='USER_PASSWORD_AUTH', AuthParameters={ 'USERNAME': username, 'PASSWORD': password, 'SCOPE': 'openid profile user/*.*' # 匹配Postman配置的scope }, ClientId=client_id ) # 获取Access Token access_token = resp['AuthenticationResult']['AccessToken'] # 调用接口,注意Authorization头的格式 url = "https://auth.appid.domain.io/oauth2/Patient" headers = { 'Authorization': f'Bearer {access_token}' } response = requests.get(url, headers=headers) print(response.status_code) print(response.text)
额外说明
如果必须用授权码模式做自动化(比如密码模式未开启),可通过selenium或playwright模拟浏览器操作完成授权流程:
- 拼接Cognito授权URL,携带
client_id、response_type=code、redirect_uri、scope参数 - 自动输入用户名密码完成登录
- 从跳转后的回调URL中提取
code参数 - 向令牌URL发POST请求,携带
code、client_id、redirect_uri、grant_type=authorization_code等参数,换取Access Token
内容的提问来源于stack exchange,提问作者Narendra Babu
相关产品推荐
相关产品推荐

