Postman - 使用密钥文件的 JWT 身份验证

Posted

技术标签:

【中文标题】Postman - 使用密钥文件的 JWT 身份验证【英文标题】:Postman - JWT authentication using key file 【发布时间】:2020-02-17 13:19:30 【问题描述】:

我正在尝试使用 Postman 测试在 Google Cloud Platform 上开发的 API:API 端点后面的 App Engine。 我有 JSON 格式的密钥文件:


  "type": "service_account",
  "project_id": "[[my_project_name]]",
  "private_key_id": "[[private_key_id]]",
  "private_key": "-----BEGIN PRIVATE KEY-----\n[[private_key]]\n-----END PRIVATE KEY-----\n",
  "client_email": "[[service_account_email]]",
  "client_id": "",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/[[service_account_email]]"

而且我可以使用 python 代码检索访问令牌:

import time
import google.auth.crypt
import google.auth.jwt

sa_keyfile='[[path_to_the_api_key_file]]'
sa_email='[[service_account_email]]'
audience='[[my_api_url]]'
expiry_length=3600
now = int(time.time())
payload = 
    'iat': now,
    "exp": now + expiry_length,
    'iss': sa_email,
    'aud':  audience,
    'sub': sa_email,
    'email': sa_email


signer = google.auth.crypt.RSASigner.from_service_account_file(sa_keyfile)
jwt = google.auth.jwt.encode(signer, payload)

print(jwt)

如果我在 Postman 中设置 OAuth 2.0 作为身份验证方法并将获得的 JWT 粘贴为 Access Token 则请求工作正常。

我想将整个 JWT 令牌操作移到 Postman 中,而无需提前调用 Python 代码。我尝试使用 Postman 的 Get New Access Token,但两个选项都不支持 JSON 密钥文件。 是否可以仅使用 Postman 从 JSON 密钥文件中获取 JWT 令牌?

【问题讨论】:

【参考方案1】:

在 GCP 中授权用户有多种方法。本质上,谷歌的首选方式是使用密钥对签署请求并将其发送给谷歌以获取应用程序的真实性并授权与上下文相关的 JWT。虽然有许多选项解释如何在服务器端进行操作,但您需要注意这些凭据实际上允许您访问平台本身。这本质上是 oAuth 工作流程,而 JWT 您可以获得不同的源,它们具有不同的范围,这反过来又允许您调用与它们相关的端点。

对于邮递员,您可以遵循文档中提到的简单 oAuth 工作流程,这很简单 Creating client IDs

当然,您需要实现服务器端部分来调用平台 API,因为它们不应该直接公开,因此在获取平台令牌时获取签名请求提供了额外的安全性。

如果您想授权最终用户,这是正确的指南:Authenticating users 同一指南还提供了有关如何授权其他“类型”应用程序的其他选项。

假设您使用 OpenApi Specs 作为访问 RESTFUL api 的标准方式。 Google 拥有大量关于使用特定身份验证提供程序来使用其服务的文档。

Choosing an Authentication Method

每种方法都有其优缺点,并选择使用具有适当权限的 JWT 的最合适的方法。

其他文档可以在这里找到Cloud Endpoints documentation

【讨论】:

我想使用现在设置的身份验证(JSON 密钥文件),因为此设置将用于最终解决方案。所以我不想仅仅为了邮递员测试而实现其他东西。 在这种情况下,您必须复制脚本获得的最终令牌。没有特定的方法来解决它,您也可以尝试为给定客户端的端点创建 api 密钥以用于测试目的,这样您就不需要任何令牌,而是密钥将用作客户端标识符。虽然它不太安全,但它应该可以工作。【参考方案2】:

您可以尝试使用 Oauth 进行身份验证,使用 Postman 发出 HTTP 请求。过程如下:

自己创建一个 JSON Web 令牌,其中包括一个标头、一个声明 集,并签名。 (签名需要服务帐户 key.json 文件中的私钥) 然后从 Google OAuth 2.0 授权请求访问令牌 服务器。 然后从 JSON 响应中获取访问令牌 授权服务器返回。

在这个link中有解释。

我认为这是可以做到的。无论哪种方式,如果必须经常这样做,我认为这不是一个实用的解决方案。

【讨论】:

【参考方案3】:

经过几个小时的研究,我在这里找到了Denis Loginov的解决方案:https://gist.github.com/dinvlad/425a072c8d23c1895e9d345b67909af0

只需将代码复制到 Postman 集合的 Pre-request Script 字段中,并在 Postman 环境中配置一些变量。

我做了这个小修改来更新 Google API 令牌服务 A 使范围也可以通过环境变量进行配置:

--- pre_request.js.orig 2021-12-01 00:54:19.000000000 +0000
+++ pre_request.js  2021-12-01 00:56:24.000000000 +0000
@@ -22,13 +22,8 @@
 const ENV_TOKEN_EXPIRES_AT = 'tokenExpiresAt';
 const ENV_ACCESS_TOKEN = 'accessToken';
+const ENV_SCOPE = 'scope';

 const JS_RSA_SIGN_SRC = 'https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js';
-const GOOGLE_OAUTH = 'https://www.googleapis.com/oauth2/v4/token';
-
-// add/remove your own scopes as needed
-const SCOPES = [
-    'https://www.googleapis.com/auth/userinfo.email',
-    'https://www.googleapis.com/auth/userinfo.profile',
-];
+const GOOGLE_OAUTH = 'https://oauth2.googleapis.com/token';

 const EXPIRES_MARGIN = 300; // seconds before expiration
@@ -74,5 +69,5 @@
             aud: GOOGLE_OAUTH,
             iss: client_email,
-            scope: SCOPES.join(' '),
+            scope: getEnv(ENV_SCOPE),
             iat,
             exp,

(My version on gist.github.com 有一些额外的环境变量重命名,因为我更喜欢snake_case。)

然后在你的 Postman 环境中设置以下变量:

serviceAccountKey(或service_account_key):插入您的整个服务帐户凭据 JSON 文件,例如:

  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "client_email": "service-account@project-id.iam.gserviceaccount.com",
  "client_id": "12345678901234567890",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-account%40project-id.iam.gserviceaccount.com",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEv...Fn9tg==\n-----END PRIVATE KEY-----\n",
  "private_key_id": "b0a...68b",
  "project_id": "project-id",
  "token_uri": "https://oauth2.googleapis.com/token",
  "type": "service_account"

scope:以空格分隔的 Google API 范围列表,例如:
"https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.metadata"

然后运行您的请求。

【讨论】:

请don't post duplicate answers。如果问题相同,请选择最好的一个来回答,然后将其他问题标记为重复。如果它们不相同,请根据每个问题的具体情况调整您的答案。

以上是关于Postman - 使用密钥文件的 JWT 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Postman 测试 jwt 身份验证

使用 Postman 和 JWT 进行 JHipster 身份验证

.NET Core Web API 密钥

带有 JWT 身份验证实现的 Django GraphQL API 仍然允许来自 Postman 的未经身份验证的请求获取数据。我该如何解决?

在 Kong API 网关中使用 .jks 密钥对 JWT 令牌进行身份验证

来自文件的 Spring Boot http 安全 jwt 密钥