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

集成Google OAuth实现Gmail登录注册:Web端获取Access Token报错排查

问题

我正在开发一款支持App和Web端的应用,要集成Google OAuth实现Gmail登录/注册,目标获取用户的name、profile_pic、dob、sub等数据。

App端已经用以下代码实现成功:

from google.oauth2 import id_token
from google.auth.transport import requests
id_info = id_token.verify_oauth2_token(token, requests.Request(), google_client_id)
print(id_info['sub'], id_info['email'])

能正常获取所有用户数据。

现在Web端尝试用Google API调用实现:Web端从Google回调请求中拿到code参数,想用code换取access_token,再用令牌获取用户数据,代码如下:

data = {
    'code': code,
    'client_id': my_client_id,
    'client_secret': my_client_secret_key,
    'redirect_uri': redirect_uri,
    'grant_type': 'authorization_code'
}
response = requests.post('https://oauth2.googleapis.com/token', data=data)
if not response.ok:
    logger.info('Could not get access token from Google.')
    return

access_token = response.json()['access_token']
response2 = requests.get(
            'https://www.googleapis.com/oauth2/v2/userinfo',
            params={'access_token': access_token}
        )
return response2.json()

现在用有效access_token能正常获取数据,但用code换access_token时出现错误,要么返回:

{'error': 'invalid_grant', 'error_description': 'Bad Request'}
要么返回:
{'error': 'unauthorized_client', 'error_description': 'Unauthorized'}
已经确认凭证正确,请问哪里出错了?

解决方案

针对你遇到的两个错误,逐个排查:

关于 unauthorized_client 错误

  • 核对OAuth客户端类型:Web端必须使用「Web应用」类型的客户端ID,不能复用App端的「Android」或「iOS」客户端ID。去Google Cloud控制台的OAuth 2.0客户端ID页面,确认当前用的client_id属于Web应用类型。
  • 检查重定向URI配置:Google Cloud控制台中,Web应用的「已授权的重定向URI」必须和代码里的redirect_uri完全一致——包括http/https协议、域名、路径,甚至大小写都不能错,多一个斜杠少一个斜杠都会触发错误。
  • 确认客户端密钥匹配:确保my_client_secret_key是当前Web应用客户端ID对应的密钥,不是其他客户端的密钥。

关于 invalid_grant 错误

  • code是否重复使用:Google的authorization code只能用一次,用过就失效。如果调试时反复用同一个code测试,或者代码里存在重复请求的逻辑,就会报这个错。
  • 检查code时效性:authorization code的有效期只有10分钟,拿到后要立即去换access_token,搁置太久会失效。
  • 重定向URI一致性:用户授权时的redirect_uri必须和换token时的redirect_uri完全相同,哪怕细微差异(比如末尾多了斜杠)都会导致错误。
  • 请求参数格式验证:确保post请求是form-data格式,你的代码用data=data是对的(requests.post默认会把字典转成form-data),但如果之前手动设置了Content-Type: application/json请求头,一定要删掉,否则会触发错误。

另外给个优化建议:Web端其实可以直接用App端类似的id_token验证方式,不用走code换token再拿用户信息的流程,更简单安全。示例代码:

from google.oauth2 import id_token
from google.auth.transport import requests

# 这里的token是从前端拿到的id_token,不是authorization code
id_info = id_token.verify_oauth2_token(token, requests.Request(), google_client_id)
# 验证签发方,确保是Google授权服务器
if id_info['iss'] not in ['accounts.google.com', 'https://accounts.google.com']:
    raise ValueError('非法签发方')
# 直接获取用户数据
print(id_info['sub'], id_info['name'], id_info['picture'])

内容的提问来源于stack exchange,提问作者Frid-j

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:16:22