当访问令牌中没有身份时,如何使用 JWT 限制用户使用他们的资源?

Posted

技术标签:

【中文标题】当访问令牌中没有身份时,如何使用 JWT 限制用户使用他们的资源?【英文标题】:How to restrict a user to THEIR resources using JWT when there is no identity in the Access Token? 【发布时间】:2019-12-24 21:46:13 【问题描述】:

我们有一个这样的 REST 资源:

/customer/customerId/bill

我们希望使用从 AWS Cognito 返回的 JWT 令牌来保护对该资源的访问。

这里的customerId 不是 Cognito 用户 ID,它是特定于域的 ID。我们已将此域特定 ID 作为自定义属性添加到 Cognito 用户。它来自 Cognito 返回的 ID 令牌,如下所示:


  "sub": "xxxxxxxx-852f-474d-aa9e-a50fd832bcb8",
  "aud": "xxxxxxxxsijed6uf54dh0uhi",
  "custom:customerId": "4044",
  "event_id": "xxxxxx-fc0c-4ffc-affa-f8987714fb2b",
  "token_use": "id",
  ....

如果我们在 Authorization: Bearer <ID Token> 中使用此 ID 令牌,我们可以编写代码(自定义授权者或应用内代码)以确保 /customer/customerId/bill 中的 customerId 等于提供的令牌中 custom:customerId 的值,我们已经保护了我们的 API。

但后来我们读到了that you should not use ID tokens to secure APIs。重点是:

(ID)令牌的受众(aud 声明)设置为应用程序的标识符,这意味着只有这个特定的应用程序才能使用此令牌。

看来我们需要发送一个访问令牌来保护 API。使用 Cognito,我们无法将用户身份的任何概念添加到访问令牌中。例如,我们不能添加像 user:4044 这样的自定义范围。

人们在这里建议的一种方法是使用提供的访问令牌在服务器端调用 Cognito 的 /userinfo 端点,以了解用户是谁。这将使我们能够编写调用此端点并声明权限的代码(自定义授权程序或应用内代码)。但它是每个请求的端点调用,这似乎很疯狂。

我们想到的一个想法是使用访问令牌来保护对 API 本身的访问,但也需要 ID 令牌作为查询参数或标头,以允许我们进行细粒度的访问控制。但这也开始让人觉得不对劲。

确定这是一个已解决的问题吗?在这里做什么是正确的?

【问题讨论】:

既然您将 JWT 令牌发送给身份验证器进行身份验证,为什么不在您的 lambda 函数中解析 JWT 令牌,如果 customerId = 他们尝试访问的路径,请允许它。 customerId 不在令牌@BrianMcCall 中 【参考方案1】:

对不起,这个问题已经有一年了,所以我的回答可能无关紧要。但是对于未来的流浪者,我会说,鉴于 cognito 在允许访问令牌中的自定义声明方面的局限性,调用 /userinfo 路由绝对是最好的方法。

API GATEWAY 允许您缓存给定用户的授权方响应,因此您不会在每个请求上都调用端点。请注意,某些实现建议将其作为确保令牌未被撤销的一种方式。

【讨论】:

以上是关于当访问令牌中没有身份时,如何使用 JWT 限制用户使用他们的资源?的主要内容,如果未能解决你的问题,请参考以下文章

如何以管理员用户身份撤销用户的访问令牌和刷新令牌?在 Oauth2 中使用 JWT

jwt 访问令牌和刷新令牌流

使用 Rails 和 React 时如何在标头中获取 JWT 令牌

如何使用 JWT Token 管理用户身份?

Cognito 用户池:如何使用刷新令牌刷新访问令牌

在 Django simple-jwt 令牌身份验证中获取后端中的当前刷新令牌