Google OAuth:授权码转访问令牌遇invalid_grant错误排查
问题
客户端通过设置ux_mode为popup的google.accounts.oauth2.initCodeClient()获取授权码后,将其传给Django后端,期望后端调用Google API。按照Google官方文档「Step 5: Exchange authorization code for refresh and access tokens」步骤配置后,执行代码时出现(invalid_grant) Bad request错误。请问哪里配置有误?是否应该使用Flow?实际场景无需重定向用户。
代码示例:
class GoogleAuthorizationView(APIView): def post(self, request): authoriztion_code = request.data.get("authorization_code") if authoriztion_code is None: return Response( {"error": "Please provide a valid authorization code"}, status=status.HTTP_400_BAD_REQUEST, ) flow = Flow.from_client_secrets_file( "path/to/client_secret.json", scopes=[ "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/user.birthday.read", ], # I only added this because it's giving me error if not present. redirect_uri="http://127.0.0.1:8000/google-authorize/", ) flow.fetch_token(code=authoriztion_code) credential = flow.credentials print(credential)
解决方案
核心错误原因及修复步骤
- 重定向URI不匹配(最常见触发原因)
Google OAuth要求三个地方的redirect_uri完全一致:前端initCodeClient配置的参数、后端Flow里设置的值、Google Cloud控制台中OAuth客户端ID的「已获授权的重定向URI」列表。
- 若你的场景无需实际跳转,前端可将
redirect_uri设为urn:ietf:wg:oauth:2.0:oob(Google官方针对无跳转授权码场景的专用URI),后端Flow里同步设置该值,同时在控制台添加这个URI。 - 若前端是SPA页面,直接将
redirect_uri设为前端页面的URL(比如http://localhost:3000),后端和控制台同步配置即可。
授权码本身无效
授权码是一次性有效且有效期仅10分钟左右,重复使用或过期都会触发invalid_grant错误。确保传给后端的是刚获取的新鲜授权码,且未被使用过。代码拼写错误
你的代码里变量名authoriztion_code少了一个字母a(正确应为authorization_code),虽当前报错不是这个导致,但可能后续引发其他问题,建议修正。
是否应该使用Flow?
完全可以用Flow,它是Google官方封装的工具类,能简化token交换流程,比手动发送HTTP请求更可靠,无需重定向的场景也能正常使用。
修正后的代码示例
class GoogleAuthorizationView(APIView): def post(self, request): # 修正拼写错误 authorization_code = request.data.get("authorization_code") if authorization_code is None: return Response( {"error": "请提供有效的授权码"}, status=status.HTTP_400_BAD_REQUEST, ) flow = Flow.from_client_secrets_file( "path/to/client_secret.json", scopes=[ "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/user.birthday.read", ], # 确保和前端initCodeClient的redirect_uri、控制台配置完全一致 redirect_uri="urn:ietf:wg:oauth:2.0:oob", ) try: flow.fetch_token(code=authorization_code) credential = flow.credentials print(credential) return Response({"access_token": credential.token, "refresh_token": credential.refresh_token}) except Exception as e: return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
内容的提问来源于stack exchange,提问作者arl
相关产品推荐
相关产品推荐

