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

Axios调用Google OAuth2刷新令牌失败但Postman成功的问题排查

Google OAuth2刷新AccessToken问题:Postman成功但Axios调用失败

问题描述

正在使用Google OAuth2流程编写函数,通过数据库存储的refresh_token调用接口获取新的access_token。Postman调用接口可成功获取结果,但用Axios编写的代码调用始终失败。已确认测试用的refresh_token、client_id和client_secret在两种调用方式中完全一致。

Postman调用配置

采用POST请求调用https://oauth2.googleapis.com/token,请求头设置Content-Type: application/x-www-form-urlencoded,通过表单形式传递refresh_token、grant_type=refresh_token、client_id、client_secret四个参数。

代码片段

export const getNewAccessToken = async (refreshToken: string): Promise<string> => {
    const url = 'https://oauth2.googleapis.com/token';
    const data = {
        refresh_token: refreshToken,
        grant_type: "refresh_token",
        client_id: process.env.GOOGLE_CLIENT_ID,
        client_secret: process.env.GOOGLE_CLIENT_SECRET,
    };

    try {
        let res = await axios.post(url, data, {
            headers: {
                'content-type': 'application/x-www-form-urlencoded'
            },
        }).then(response => {
            debugger;
        }).catch(e => {
            // 总是进入这里的catch
            debugger;
        });
    } catch (e) {
        debugger;
    }
}

错误信息

调用触发400 Bad Request错误,返回内容为:

{error: 'unsupported_grant_type', error_description:'Invalid grant_type: '}

补充信息

Postman生成的curl命令:

curl --location --request POST 'https://oauth2.googleapis.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'refresh_token=[与代码中一致的refresh_token]' \
--data-urlencode 'client_id=[同上]' \
--data-urlencode 'client_secret=[同上]' \
--data-urlencode 'grant_type=refresh_token'

问题

  1. 是否忽略了什么明显的问题?
  2. 可以尝试哪些调试方法?

曾尝试查看错误对象e,但无法在ClientRequest对象中找到原始请求信息。


问题原因

你设置了Content-Type: application/x-www-form-urlencoded请求头,但Axios默认会把JavaScript对象序列化为JSON格式,而非表单编码格式。Google OAuth2接口无法解析JSON格式的参数,导致实际未正确传递grant_type参数,因此返回unsupported_grant_type错误。

解决方法

有两种方式可以修正参数编码问题:

  1. 使用URLSearchParams格式化参数
    将data对象转换为URLSearchParams实例,Axios会自动处理表单编码:

    const data = new URLSearchParams({
        refresh_token: refreshToken,
        grant_type: "refresh_token",
        client_id: process.env.GOOGLE_CLIENT_ID,
        client_secret: process.env.GOOGLE_CLIENT_SECRET,
    });
    
  2. 使用qs库序列化参数
    先安装qs依赖:

    npm install qs
    

    然后在代码中用qs序列化参数:

    import qs from 'qs';
    
    // ...
    const data = qs.stringify({
        refresh_token: refreshToken,
        grant_type: "refresh_token",
        client_id: process.env.GOOGLE_CLIENT_ID,
        client_secret: process.env.GOOGLE_CLIENT_SECRET,
    });
    

调试方法

  • 打印实际请求内容:添加Axios请求拦截器,输出请求体和请求头,确认参数格式是否正确:
    axios.interceptors.request.use(config => {
        console.log('请求体:', config.data);
        console.log('请求头:', config.headers);
        return config;
    });
    
  • 对比curl与Axios请求:将Axios发送的参数格式和curl的--data-urlencode格式对比,确认参数编码是否一致。
  • 直接用curl验证参数:把代码中的参数替换到curl命令中执行,验证参数本身的有效性。

内容的提问来源于stack exchange,提问作者Allen Y

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:15:35