Google登录获取用户信息报错:OAuth2范围无效或不兼容旧API
问题描述
实现Google登录功能时,服务器通过授权码获取token后,调用用户信息接口返回以下错误:
You are receiving this error either because your input OAuth2 scope name is invalid
or it refers to a newer scope that is outside the domain of this legacy API.This API was built at a time when the scope name format was not yet standardized.
This is no longer the case and all valid scope names (both old and new) are catalogued
at https://developers.google.com/identity/protocols/oauth2/scopes. Use that webpage to
lookup (manually) the scope name associated with the API you are trying to call and use
it to craft your OAuth2 request.
相关代码及配置:
获取token的代码:
googleTokenEndpoint = os.getenv("GOOGLE_TOKEN_ENDPOINT") googleLoginTokenRequest = post(googleTokenEndpoint, data={ "code": requestArgs["code"], "client_id": os.getenv("GOOGLE_LOGIN_CLIENT_ID"), "client_secret": os.getenv("GOOGLE_LOGIN_CLIENT_SECRET"), "redirect_uri": os.getenv("GOOGLE_LOGIN_CALLBACK_URL"), "grant_type": "authorization_code" }) if not googleLoginTokenRequest.ok: return responseHandler.badGateway("Google token endpoint returned error: " + str(json.loads(googleLoginTokenRequest.content))) googleLoginTokenJson = json.loads(googleLoginTokenRequest.content) if "error" in googleLoginTokenJson: return responseHandler.badGateway("Google token endpoint returned error: " + googleLoginTokenJson)
调用用户信息的代码:
googleLoginUserinfoRequest = get(os.getenv("GOOGLE_SCOPE_USERINFO_ENDPOINT"), params={ "access_token": googleLoginTokenJson["access_token"] }) print(googleLoginUserinfoRequest.content)
.env配置:
GOOGLE_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token" GOOGLE_SCOPE_USERINFO_ENDPOINT = "https://www.googleapis.com/auth/userinfo" GOOGLE_AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"
错误原因分析
- 接口地址混淆:
GOOGLE_SCOPE_USERINFO_ENDPOINT配置的是OAuth2的权限范围标识,而非用户信息接口的实际请求地址。https://www.googleapis.com/auth/userinfo是scope值,不是可直接调用的API端点。 - 缺少授权权限:引导用户跳转到Google授权页时,未添加用户信息相关的scope(如
openid、email、profile),导致获取的access_token没有访问用户信息的权限。
修复方案
1. 修正用户信息接口地址
用户信息的正确API端点是https://www.googleapis.com/oauth2/v2/userinfo,修改.env中的对应配置项。
2. 补充授权Scope
构造Google授权页URL时,必须携带必要的scope参数,至少包含openid(OpenID Connect流程必需),加上email和profile可获取用户邮箱、基本资料等信息。
3. 调整代码逻辑
确保授权请求携带正确的scope,同时使用修正后的接口地址调用用户信息API。
具体修改示例
修改.env配置
GOOGLE_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token" # 修正为用户信息接口地址 GOOGLE_USERINFO_ENDPOINT = "https://www.googleapis.com/oauth2/v2/userinfo" GOOGLE_AUTHORIZATION_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth" # 新增授权所需的scope配置 GOOGLE_LOGIN_SCOPES = "openid email profile"
调整用户信息调用代码
# 使用修正后的接口地址 googleLoginUserinfoRequest = get(os.getenv("GOOGLE_USERINFO_ENDPOINT"), params={ "access_token": googleLoginTokenJson["access_token"] }) print(googleLoginUserinfoRequest.content)
补充授权页跳转逻辑(关键)
引导用户跳转到Google授权页时,必须携带scope参数,示例代码:
# 构造授权URL auth_url = f"{os.getenv('GOOGLE_AUTHORIZATION_ENDPOINT')}?response_type=code&client_id={os.getenv('GOOGLE_LOGIN_CLIENT_ID')}&redirect_uri={os.getenv('GOOGLE_LOGIN_CALLBACK_URL')}&scope={os.getenv('GOOGLE_LOGIN_SCOPES')}" # 重定向到授权页 return redirect(auth_url)
验证要点
- 确认授权URL中包含
openid、email、profile这些scope - 获取token后调用修正后的接口,应返回包含用户id、邮箱、姓名等信息的JSON数据
内容的提问来源于stack exchange,提问作者LLL

