如何在 Postman 集合中保留 OAuth2 令牌(或使用刷新令牌)?

How to persist an OAuth2 token (or use a refresh token) in Postman collections?

目标

能够 运行 收集,而无需在 运行 收集收集之前单独通过每个调用的授权过程。

我有什么attempted/noticed

  1. 在Postman中使用OAuth2 authorization helper时,我还没有发现一种方法来保存返回的刷新令牌,因此在访问令牌过期时使用它来获取新的。 (我建议将此功能放入 Postman Github 问题的帮助器中。)

  2. 我尝试在集合的开头创建几个步骤来复制助手,但无法通过需要用户交互的步骤 approve/deny(这是有道理的因为否则会带来安全风险)。但是,我似乎也不知道如何像 OAuth2 助手那样提示用户。

  3. 我对刷新令牌的期望降低了一个档次,我认为我可以简单地 运行 在列表中的第一个测试中进行身份验证,以某种方式保存访问令牌在全局或环境变量中,然后在所有后续测试中使用该令牌,但我还没有找到一种方法来保存通过 OAuth2 助手生成的访问令牌。

我很想知道是否有解决方案可以使集合能够 运行 以最少的授权投入。随着在集合中编写的测试越来越多,这些测试都使用 OAuth2 授权,这一点变得更加重要。

旁注:我一直在使用 Postman mac 客户端,以防我不知道的客户端有所不同。

我找到了答案 here on github

首先,设置这些环境变量:

  • url :(您的 API 端点)
  • access_token : (空白)
  • refresh_token : (空白)
  • client_id : (你的 client_id)
  • client_secret : (你的 client_secret)
  • username : (您的用户名)
  • password : (您的密码)

接下来,创建一个新调用,使用 password grant_type.

获取 access_token

就我而言,我 POST 到 {{url}}/access_token。与此呼叫一起发送的是 form-data key/value 对中指定的以下信息 Body 选项卡:

  • grant_type : password
  • username : {{username}}
  • password : {{password}}
  • client_id : {{client_id}}
  • client_secret : {{client_secret}}

发送这个 POST 会产生类似这样的响应:

{
  "access_token": "kciOMpcmRcGTKfoo",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "DMGAe2TGaFbar"
}

然后,在“测试”选项卡中,我添加了以下代码来分配两个环境变量,access_tokenrefresh_token

var data = JSON.parse(responseBody);
postman.setEnvironmentVariable("access_token", data.access_token);
postman.setEnvironmentVariable("refresh_token", data.refresh_token);

注意:我也在那里进行了测试,只是为了确保至少这个调用也能正常工作,尽管这与原始问题无关:

var jsonData = JSON.parse(responseBody);
tests["token_type is Bearer"] = jsonData.token_type === "Bearer";

现在我创建的任何新调用都可以使用第一次调用生成的 access_token 作为环境变量,如下所示:{{access_token}}。就我而言,我转到 call/test 中的 Headers 选项卡并添加此 key/pair:

  • Authorization : Bearer {{access_token}}

奖励积分:我没有在这里给出示例,但理论上我可以添加一个 pre-request 脚本来测试当前 (non-blank) access_token 与 API,如果失败,则使用给定的 (non-blank) refresh_token 获取一个新的。这样我就不用担心访问令牌过期了。

综上所述,我不喜欢这个解决方案,因为它需要将第一个 access_token 调用添加到我的 collection 中的每个 sub-folder 因为如果我想 运行 只有 sub-folder 而不是整个 collection,我需要确保我有一个新鲜的 access_token。不这样做意味着当 access_token 过期时所有测试都会失败。如果您从不在 Collection Runner 中单独 运行 sub-folders,您可以只创建一个 access_token 调用并将其设置为对 [=129= 的第一个调用] 在 collection 中。

但是,出于这个原因,我还不打算将其标记为正确答案。我猜有比我想出的更好的答案 - 理想情况下我不必将相同的 access_token call/test 复制到每个 sub-folder,但确实得到自动化的好处,non-interactive 测试具有 运行 单独 sub-folder 或整个 collection 的灵​​活性。

好的,首先输入您的 OAUTH 令牌 URL,单击正文选项卡,然后填写这些 POST 参数: client_id、grant_type、用户名、密码、覆盖。

然后,单击“测试”选项卡,输入此文本,然后按“发送”:

var data = JSON.parse(responseBody);
postman.setGlobalVariable("access_token", data.access_token);
postman.setGlobalVariable("refresh_token", data.refresh_token);

然后输入您的一个应用程序 URLs,单击 Headers 选项卡,然后输入值为 Bearer {{access_token}} 的参数 Authorization。然后点击发送。

瞧!

其他两个答案都是正确的。但是,还有另一种方法可以做到这一点,并且不需要任何额外的请求。 此方法使用需要 access_token 的请求的 pre-request 脚本。 您可以使用 pm.sendRequest 中记录的 postman-sandbox-api

从预请求脚本发送一个请求到 auth-token URL。发送所有凭据和刷新令牌。在响应中,您将获得访问令牌,然后您可以将其保存在环境中或仅保存在内存中,然后使用它。

示例代码 我在这里做了一个要点 https://gist.github.com/harryi3t/dd5c61451206047db70710ff6174c3c1

// Set all these variables in an environment or at collection level
let tokenUrl = pm.variables.get('tokenUrl'),
    clientId = pm.variables.get('clientId'),
    clientSecret = pm.variables.get('clientSecret'),
    refreshToken = pm.variables.get('refreshToken'),
    requestOptions = {
      method: 'POST',
      url: tokenUrl,
      body: {
        mode: 'formdata',
        formdata: [
            {
                key: 'grant_type',
                value: 'refresh_token'
            },
            {
                key: 'client_id',
                value: clientId
            },
            {
                key: 'client_secret',
                value: clientSecret
            },
            {
                key: 'refresh_token',
                value: refreshToken
            }
        ]
      }
    };

console.log({ requestOptions });

pm.sendRequest(requestOptions, (err, response) => {
  let jsonResponse = response.json(),
      newAccessToken = jsonResponse.access_token;

  console.log({ err, jsonResponse, newAccessToken })

  // If you want to persist the token
  pm.environment.set('accessToken', newAccessToken);

  // Or if you just want to use this in the current request and then discard it
  pm.variables.set('accessToken', newAccessToken);
});

现在发送请求时,变量 accessToken 将出现,您可以像这样在请求中使用它:

注意:Oauth2中有4种Grant Types。其中两个(授权代码和隐式)需要与无法自动化的浏览器进行交互。但是如果服务器提供了refresh-token那么上面的脚本可以帮助你得到access-token。其他两种类型(客户端凭据和密码凭据)不需要任何浏览器交互。所以这些可以从脚本中自动完成。如果您使用的是 client_credentials,您可以调整上述脚本以从 authUrl 获取 code,然后从 AuthTokenUrl.[=22 获取 access_token =]

首先,来自线程的。现在,考虑这个问题的后半部分(基于评论):

如何使用刷新令牌?

  1. 创建一个新的 POST 请求(最容易复制您创建的用于采购 access_token 的请求)。

  1. 在正文中,删除 usernamepassword。将 grant_type 替换为 "refresh_token"。添加值为“{{refresh_token}}”的 refresh_token,这是对您首次授权时创建的变量的引用(您还记得 ?)

  1. 确保刷新请求的测试部分覆盖 access_token 和 refresh_token 的 Postman 变量。为什么?因为每当您执行刷新时,您都会获得另一个刷新令牌。如果您不捕获新的刷新令牌,您最终将使用旧的刷新令牌并且 API 将拒绝它。然后你需要从第一步重新运行整个事情(即从)。

  1. 现在,当您的授权到期时,您不需要 运行 包含您的用户名和密码的原始请求。您可以使用我们刚刚创建的请求永久刷新。这在您进行协作并需要共享 API 访问权限但又不想共享 username/passwords.
  2. 时特别有用

HTH!