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

Posted

技术标签:

【中文标题】如何在 Postman 集合中保留 OAuth2 令牌(或使用刷新令牌)?【英文标题】:How to persist an OAuth2 token (or use a refresh token) in Postman collections? 【发布时间】:2016-05-06 09:12:32 【问题描述】:

目标

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

我尝试过/注意到的事情

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

    我尝试在集合的开头创建几个步骤来复制帮助程序,但无法通过需要用户交互来批准/拒绝的步骤(这是有道理的,否则会存在安全风险)。但是,我似乎也不知道如何提示用户,就像 OAuth2 帮助程序那样。

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

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

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

【问题讨论】:

【参考方案1】:

好的,首先输入您的 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);

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

瞧!

【讨论】:

谢谢您,您的回答很棒!您能否通过举例说明如何使用 refresh_token 来完成它。 是的,令人惊叹的答案,赞成...如果你能包括一个 refres_token 的例子,那就太棒了 我有一个类似的 grant_type = client_credentials 配置,效果很好。但是现在我有一个案例需要使用grant_type=authorization_code。对于这个,这个解决方案不起作用,因为必须显示一个登录弹出窗口..这种情况有解决方案吗? 在我的情况下,我得到一个 pm.setGlobalVariable() not found 错误。用 postman.setGlobalVariable() 修复【参考方案2】:

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

如何使用刷新令牌?

    创建一个新的 POST 请求(最容易复制您为获取 access_token 而创建的请求)。

    在正文中,删除usernamepassword。将grant_type 替换为“refresh_token”。添加带有值“refresh_token”的refresh_token,这是对您第一次授权时创建的变量的引用(您还记得read this answer吗?

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

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

HTH!

【讨论】:

【参考方案3】:

其他两个答案都是正确的。但是,还有另一种方法可以做到这一点,并且不需要任何额外的请求。 此方法使用需要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 种授权类型。其中两个(身份验证代码和隐式)需要与无法自动化的浏览器交互。但是如果服务器提供了 refresh-token,那么上面的脚本可以帮助你获取 access-token。其他两种类型(客户端凭据和密码凭据)不需要任何浏览器交互。所以这些可以从脚本中自动化。如果您使用的是 client_credentials,则可以调整上述脚本以从 authUrl 获取 code,然后从 AuthTokenUrl 获取 access_token

【讨论】:

我喜欢使用预请求脚本的想法,但您是否必须在每个请求中配置脚本?有没有办法为每个环境执行一个脚本? 这些请求是否与不同的身份验证服务器(如 Google 和 Github)通信并需要不同的令牌?如果是,那么是的,您将不得不复制代码。否则,您可以将令牌存储在变量中并重复使用。 @nettie old,但以防万一:您可以将预请求脚本存储在集合中,该脚本用于该集合中发出的每个请求。【参考方案4】:

我找到了答案here on github。

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

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

接下来,使用password grant_type 创建一个新的调用,获取access_token

就我而言,我发帖到url/access_token。与此调用一起发送的是以下信息,即“正文”选项卡中指定的 form-data 键/值对:

grant_typepassword username : username password : password client_id : client_id client_secretclient_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。就我而言,我在调用/测试中转到 Headers 选项卡并添加此密钥/对:

AuthorizationBearer access_token

加分:我在这里没有给出示例,但理论上我可以添加一个预请求脚本,针对 API 测试当前(非空白)access_token,如果失败,获取一个新脚本使用给定的(非空白)refresh_token。这样我就不用担心访问令牌过期了。

总而言之,我不喜欢这个解决方案,因为它需要将第一个 access_token 调用添加到我的集合中的每个子文件夹,因为如果我只想运行一个子文件夹而不是整个集合,我需要确保我有一个新的 access_token。不这样做意味着当 access_token 过期时所有测试都会失败。如果您从未在 Collection Runner 中单独运行子文件夹,则只需创建一个 access_token 调用并将其设置为在集合中运行的第一个调用即可。

但是,出于这个原因,我还不打算将此标记为正确答案。我猜有一个比我想出的更好的答案 - 理想情况下,我不必将相同的 access_token 调用/测试复制到每个子文件夹中,但确实可以获得自动化、非交互式的好处测试可以灵活地运行子文件夹本身或整个集合。

【讨论】:

已经有一段时间了,由于没有其他人回答,我将其标记为正确。 我对“测试”选项卡以及它如何与我的通话联系感到迷失。

以上是关于如何在 Postman 集合中保留 OAuth2 令牌(或使用刷新令牌)?的主要内容,如果未能解决你的问题,请参考以下文章

使用postman测试oauth2.0认证服务中出现OAuth出现Bad credentials

使用Postman访问OAuth2保护的WebAPI

使用 Postman 的简单 Spring Oauth2 流程

如何在预请求脚本中更改 Postman 环境?

postman——集合——执行集合——分享(导出导入)集合运行结果

Postman中文文档——历史记录(History)