【问题标题】:Retrieving OAuth2 Token Via Node-Fetch通过 Node-Fetch 检索 OAuth2 令牌
【发布时间】:2020-10-22 21:50:36
【问题描述】:

问题是我正在尝试检索 OAuth2 令牌。由于request 已被弃用,我为此使用node-fetch。虽然我可以让它与request 一起工作,但我不能与node-fetch 一起工作。

我已经阅读了很多关于这里的帖子,但似乎没有一个真正给出真正有效的一致答案。我承认我看起来还不够好。我将其包装在测试中可能也很复杂,但由于我收到的错误消息,感觉并非如此。

这是有效的代码(请注意,我必须更改详细信息以保护内部 URL):

var request = require("request");

var options = {
  method: "POST",
  url: "https://some-url/realms/my-realm/protocol/openid-connect/token",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  form: {
    username: "JeffUser",
    password: "jeff-password",
    grant_type: "password",
    client_id: "jeff-client",
    client_secret: "jeff-client"
  }
};

request(options, function(error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
})

这行得通,我得到了令牌。这是我在node-fetch(包含在测试中)中尝试的失败:

const assert = require("chai").assert;
const fetch = require("node-fetch")

describe("Test API", function() {
  let api_token = "";

  it("gets a token", async function() {
    api_token = await fetch("https://some-url/realms/my-realm/protocol/openid-connect/token", {
      method: "post",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      form: {
        username: "JeffUser",
        password: "jeff-password",
        grant_type: "password",
        client_id: "jeff-client",
        client_secret: "jeff-client"
      }
    }).then (response => {
      return response.json();
    });

    console.log(token);
  });
});

这里发生的是我从该测试中得到以下输出:

{
  error: 'invalid_request',
  error_description: 'Missing form parameter: grant_type'
}

我已尝试按照某些搜索的建议将 form 更改为 body,但这似乎没有任何效果。我尝试用 JSON.stringify() 包装 form: { } 数据,正如其他一些搜索所建议的那样,但这也导致了同样的错误被报告。

【问题讨论】:

  • 需要body而不是form。而且您可能需要自己处理正确格式的数据编码,不确定是否有任何自动为您做这件事。
  • github.com/node-fetch/node-fetch#post-with-form-parameters - 使用URLSearchParams 之类的东西以application/x-www-form-urlencoded 要求的正确格式提供您的数据。
  • @CBroe:谢谢。但是不清楚为什么request 代码有效,我不使用“body”。此外,没有其他逻辑(我知道)专门针对编码做任何事情。基本上我正在尝试将request 中的工作内容移植到node-fetch。我会试试URLSearchParams 的事情。
  • 就是这样! URLSearchParams 是我需要的。谢谢!

标签: javascript oauth-2.0 node-fetch


【解决方案1】:

这要感谢@CBroe,他在 cmets 中为我提供了答案。我会将解决方案放在这里,以供遇到此问题的其他人使用。这是我必须做的:

const assert = require("chai").assert;
const fetch = require("node-fetch")

const params = new URLSearchParams();

params.append("grant_type", "password");
params.append("username", "JeffUser");
params.append("password", "jeff-password");
params.append("client_id", "jeff-client");
params.append("client_secret", "jeff-client");


describe("Test API", function() {
  let api_token = "";

  it("gets a token", async function() {
    api_token = await fetch("https://some-url/realms/my-realm/protocol/openid-connect/token", {
      method: "post",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: params
    }).then (response => {
      return response.json();
    });

    console.log(token);
  });
});

我确保使用body 而不是form。我还使用URLSearchParams 创建了一系列参数,并将其传递给body 参数。这就是诀窍!我现在得到了授权令牌。

【讨论】:

    【解决方案2】:
    const buffer = require("buffer")
    const fetch = require("node-fetch")
    
    let url = 'www.exampl.com/token';
    let client_id = '123';
    let client_secret = '323';
    let username = 'test';
    let password = 'test';
    
    let basicAuth = buffer.from(`${client_id}:${client_secret}`).toString("base64");
    
    const response = await fetch(url, {
     method:"POST",
     headers:{ 
        "Content-Type": "application/x-www-form-urlencoded",
        Accept: "application/json; charset=UTF-8", 
         Authorization: `Basic ${basicAuth}`, 
        },
      body:`grant_type=password&username=${username}&password=${password}&scope=xfds`,
    });
    
    let token = await response.json();
    
    console.log(token)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 2011-10-04
      • 2015-02-26
      • 2019-07-09
      • 2016-02-15
      • 2021-10-25
      相关资源
      最近更新 更多