尝试用 google 交换令牌的授权码时请求失败 401

401 failed request when trying to exchange authorization code for tokens w/ google

我在 Google OAuth 流程中遇到这个特定步骤:“交换令牌的授权代码”(在 Google 开发人员的“OAuth 2.0 游乐场”,第 2 步中调用) .

function getGoogleAuthURL() {
    const rootUrl = "https://accounts.google.com/o/oauth2/v2/auth";
    const options = {
      redirect_uri: `http://${HOST}:${PORT}/auth/google`,
      client_id: `${googleConfig.clientId}`,
      access_type: "offline",
      response_type: "code",
      prompt: "consent",
      scope: defaultScope.join(" "), // A list of scopes declared in the file scope
    };
    return `${rootUrl}?${querystring.stringify(options)}`;
}

app.get("/auth/google/url", (req, res) => {
    res.redirect(getGoogleAuthURL());
});

将用户重定向到同意提示后,上面的代码将用户重定向到:http://${HOST}:${PORT}/auth/google,提供获取刷新和访问令牌所需的 'Authorization code'。

app.get(`/auth/google`, async (req, res) => {
    const code = req.query.code
    const tokens = await getTokens({code})
});

我的问题来自用于POST和return标记的getToken()函数。

function getTokens({code}) {
    const url = 'https://accounts.google.com/o/oauth2/token';
    const values = {
      code,
      client_id: googleConfig.clientId,
      client_secret: googleConfig.clientSecret,
      redirect_uri: googleConfig.redirect,
      grant_type: 'authorization_code',
    };
    console.log(`${url}${querystring.stringify(values)}`)

    return axios
      .post(url, querystring.stringify(values), {
        headers: {
          'Content-Type': 'application/x-www-form-url-encoded',
        },
      })
      .then((res) => res.data)
      .catch((error) => {
        throw new Error(error.message);
    });
}

我从 .catch((error) ...

得到 Error: Request failed with status code 401

console.log(${url}${querystring.stringify(values)})给出完整的内置link,即:

https://accounts.google.com/o/oauth2/tokencode=X&client_id=X.apps.googleusercontent.com&client_secret=X&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fdashboard%3B&grant_type=authorization_code

我解决的问题:

我已经将我的 'request' 和 'url' 与 Google 开发人员的“OAuth 2.0 游乐场”上的那些进行了多次比较,语法似乎不是字段有问题,虽然我对 /tokencode=... 之间的标点表示怀疑,我改为 /token?code=...,但仍然导致请求失败 (401) .

我也一直在使用两种不同的 ${url}:

https://oauth2.googleapis.com/token https://accounts.google.com/o/oauth2/v2/auth

但我知道我应该使用哪一个。

axios 的第二个参数 post 是正文,不是查询参数。

您可以在第三个参数中设置params。

axios.post(url, {}, {
   headers: { 'Content-Type': 'application/x-www-form-url-encoded' },
   params: {
     tokencode: values.code, 
     // etc
   }
}

您还缺少 values 对象中 code 的键。

您也可以只在第一个参数中附加查询字符串:

axios.post(url + querystring.stringify(values),{}, {
        headers: {
          'Content-Type': 'application/x-www-form-url-encoded'
        },
      })