通过 Node-Fetch 检索 OAuth2 令牌

Jef*_*man 7 javascript oauth-2.0 node-fetch

问题是我正在尝试检索 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);
})

Run Code Online (Sandbox Code Playgroud)

这有效,我得到了令牌。这是我正在尝试的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);
  });
});

Run Code Online (Sandbox Code Playgroud)

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

{
  error: 'invalid_request',
  error_description: 'Missing form parameter: grant_type'
}
Run Code Online (Sandbox Code Playgroud)

我尝试按照一些搜索的建议进行更改formbody但这似乎没有任何效果。我尝试按照其他一些搜索的建议form: { }用 a 包装数据JSON.stringify(),但这也导致报告相同的错误。

Jef*_*man 5

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

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);
  });
});
Run Code Online (Sandbox Code Playgroud)

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