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

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)
解决方案

核心错误原因及修复步骤

  1. 重定向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),后端和控制台同步配置即可。
  1. 授权码本身无效
    授权码是一次性有效且有效期仅10分钟左右,重复使用或过期都会触发invalid_grant错误。确保传给后端的是刚获取的新鲜授权码,且未被使用过。

  2. 代码拼写错误
    你的代码里变量名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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:10:25