78

我正在引用另一篇讨论使用 JWT 刷新令牌的 SO 帖子。

JWT(JSON Web Token)自动延长过期时间

我有一个具有非常通用架构的应用程序,我的客户端(Web 和移动设备)与 REST API 通信,然后再与服务层和数据层通信。

在此处输入图像描述

我了解 JWT 令牌身份验证,但我对如何使用刷新令牌有点困惑。

我希望我的 JWT 身份验证具有以下属性:

  1. JWT Token 的有效期为 2 小时。

  2. 客户端每小时刷新一次令牌。

  3. 如果用户令牌未刷新(用户处于非活动状态且应用程序未打开)并过期,则他们需要在想要恢复时登录。

我看到很多人声称使用刷新令牌的概念可以使这成为更好的体验,但是,我看不到这样做的好处。管理它似乎增加了复杂性。

我的问题如下:

  1. 如果我要使用刷新令牌,那么为该令牌的良好实践长期到期是否仍然有益?
  2. 如果我要使用刷新令牌,该令牌会与 userId 和/或 JWT 令牌一起保存吗?
  3. 当我每 1 小时更新一次令牌时,这是如何工作的?我是否要创建一个接收 JWT 令牌或刷新令牌的端点?这会更新我的原始 JWT 令牌的到期日期,还是创建一个新令牌?
  4. 鉴于这些详细信息,是否需要刷新令牌?似乎如果用户只是使用 JWT 令牌来获取新令牌(根据上面的链接),那么刷新令牌已过时。
4

3 回答 3

175

稍后让我来回答您的问题,并从实际讨论刷新令牌的全部目的开始。

所以情况是:

用户打开应用程序并提供他的登录凭据。现在,该应用程序很可能正在与 REST 后端服务进行交互。REST 是无状态的,无法授权访问 API。因此,到目前为止,在讨论中,无法检查授权用户是否正在访问 API,或者只是一些随机请求通过。

现在为了能够解决这个问题,我们需要一种方法来知道请求来自授权用户。所以,我们所做的是引入一种叫做访问令牌的东西。所以现在一旦用户成功通过身份验证,他就会获得一个访问令牌。这个令牌应该是一个长且高度随机的令牌(以确保它不会被猜到)。这就是 JWT 发挥作用的地方。现在您可能/可能不想在 JWT 令牌中存储任何用户特定的详细信息。理想情况下,您只想在 JWT 中存储非常简单、极其不敏感的细节。JWT(正在使用的库)本身负责操作 JWT 哈希以检索其他用户的详细信息(IDOR 等)。

所以,现在,我们的授权访问问题已经解决了。

现在我们讨论一个攻击场景。假设使用上述所有用户 Alice,使用该应用程序,拥有授权访问令牌,现在她的应用程序可以向所有 API 发出请求并根据她的授权检索数据。

假设Alice以某种方式丢失了访问令牌,或者换句话说,对手 Bob 获得了对 Alice 的访问令牌的访问权。现在,尽管 Bob 未经授权,但可以向 Alice 授权的所有 API 发出请求。

我们理想中不想要的东西。

现在这个问题的解决方案是:

  1. 要么检测到有这种事情发生。
  2. 减少攻击窗口本身。

仅使用访问令牌,很难实现上述条件 1,因为无论是 Alice 还是 Bob,都使用相同的授权令牌,因此来自两个用户的请求是不可区分的。

因此,我们尝试实现上述 2,因此我们为访问令牌的有效性添加了一个过期时间,例如访问令牌在“t”(短期)时间内有效。

它有什么帮助?好吧,即使 Bob 拥有访问令牌,他也只能在它有效时使用它。一旦过期,他将不得不再次取回它。现在,当然,你可以说他可以像第一次一样得到它。但话又说回来,没有什么比 100% 安全!

上述方法仍然存在问题,并且在某些情况下是不可接受的。当访问令牌过期时,它将要求用户输入他的登录凭据并再次获得授权的访问令牌,至少在移动应用程序的情况下,这是一种糟糕的(不可接受的)用户体验。

解决方案:这就是刷新令牌的用武之地。它也是一个随机的不可预测的令牌,它也首先与访问令牌一起发布给应用程序。这个刷新令牌是一个非常长寿命的特殊令牌,它确保一旦访问令牌过期,它就会向服务器请求新的访问令牌,从而无需用户重新输入他的登录凭据来检索一个新的授权访问令牌,一旦现有的已过期。

现在您可能会问,Bob 也可以访问刷新令牌,类似于他破坏访问令牌的方式。是的。他可以。然而,现在很容易识别这种事件,这在仅使用访问令牌的情况下是不可能的,并采取必要的措施来减少造成的损害。

如何?

对于每个经过身份验证的用户(通常在移动应用程序的情况下),都会向应用程序颁发一对一映射的刷新令牌和访问令牌对。因此,在任何给定时间点,对于单个经过身份验证的用户,只有一个访问令牌对应于刷新令牌。现在假设如果 Bob 泄露了刷新令牌,他将使用它来生成访问令牌(因为访问令牌是唯一被授权通过 API 访问资源的东西)。一旦 Bob(攻击者)请求使用新生成的访问令牌,因为 Alice(真正的用户)的访问令牌仍然有效,服务器就会将此视为异常,因为对于单个刷新令牌,在一次。识别异常,服务器将销毁有问题的刷新令牌以及所有这些,它的关联访问令牌也将失效。从而防止对任何需要资源的授权的任何进一步访问,无论是真实的还是恶意的。用户 Alice 将被要求再次使用她的凭据进行身份验证并获取一对有效的刷新和访问令牌。

当然,您仍然可以争辩说 Bob 可以再次获得对刷新和访问令牌的访问权并重复上面的整个故事,这可能会导致对真正的真正客户 Alice 的 DoS,但是再一次没有什么比 100% 安全.

同样作为一种好的做法,刷新令牌应该有一个到期时间,虽然很长。

于 2016-03-29T09:38:10.857 回答
20

我相信在这种情况下,您可以单独使用访问令牌,让您的客户的生活更轻松,同时保持刷新令牌的安全优势。

这就是它的工作方式:

  1. 当您的用户使用凭据(用户名/密码)登录时,您会返回一个短暂的 JWT。您还可以在存储位置创建一个数据库记录:

    • 智威汤逊ID
    • 用户身份
    • IP地址
    • 用户代理
    • 一个valid标志(默认为 TRUE)
    • 创建时间
    • 更新时间
  2. 您的客户端在每个请求中提交 JWT。只要 JWT 没有过期,它就可以访问资源。如果 JWT 过期,您将在后台刷新它并返回资源和X-JWT带有新 JWT 的附加标头。

  3. 当客户端收到带有X-JWT标头的响应时,它会丢弃旧的 JWT 并将新的 JWT 用于将来的请求。

刷新 JWT 如何在服务器上工作

  1. 使用 JWT id 查找匹配的数据库记录。
  2. 检查valid标志是否仍然为真,否则拒绝。
  3. 或者,您可以将请求 IP 地址和用户代理与存储的 IP 地址和用户代理进行比较,如果某些内容看起来可疑,则决定拒绝。
  4. 或者,您可以检查 db 记录的 createdAt 或 updatedAt 字段,并在时间过长时决定不刷新。
  5. 更新updatedAtdb 记录中的字段。
  6. 返回新的 JWT(它基本上是过期 JWT 的副本,但具有延长的过期时间)。

这种设计还可以让您选择撤销用户的所有令牌(例如,如果用户丢失了他的手机或更新了他的密码)。

好处:

  • 您的客户端永远不必检查过期时间或发出刷新令牌请求,它所做的只是检查X-JWT响应的标头。
  • 您可以根据 IP 地址、用户代理、最大令牌年龄或这些的组合添加自定义刷新逻辑。
  • 您可以为用户撤销部分或全部令牌。
于 2016-12-20T19:42:48.070 回答
6

如果我要使用刷新令牌,那么为该令牌的良好实践长期到期是否仍然有益?

刷新令牌是长期存在的,访问令牌是短暂的。

如果我要使用刷新令牌,该令牌会与 userId 和/或 JWT 令牌一起保存吗?

它将在客户端上作为单独的令牌与 JWT 一起保存,但不在 JWT 内部。UserID/UID 可以存储在 JWT 令牌本身中。

当我每 1 小时更新一次令牌时,这是如何工作的?我是否要创建一个接收 JWT 令牌或刷新令牌的端点?这会更新我的原始 JWT 令牌的到期日期,还是创建一个新令牌?

是的,您需要一个单独的服务来发布和刷新令牌。它不会更新现有 JWT 令牌的到期时间。令牌只是经过 base64 编码的 JSON 字段值对。所以改变数据,改变输出。该令牌还具有发行日期,至少会在每个新发行(刷新)时更改。因此,每个代币都将是独一无二的和新的。旧令牌将自动过期,因此您需要所有访问令牌都过期,否则它们将永远存在。

此处的另一个答案指出,当您发行新令牌时,旧令牌会被销毁。事实并非如此。令牌不能被销毁。事实上,您可以通过不断联系身份验证服务器并使用刷新令牌请求新的新令牌来获取数百个令牌。这些访问令牌中的每一个都将在其到期之前有效。所以到期是必要的,而且应该很短。

考虑到这些细节,真的需要刷新令牌吗?似乎如果用户只是使用 JWT 令牌来获取新令牌(根据上面的链接),那么刷新令牌已过时。

JWT 令牌具有客户端声明。例如is_manager:true,对 JWT 令牌的声明可能允许访问经理级别的功能。现在,如果您决定将用户从经理降级为承包商,则不会立即生效。用户可能仍在使用旧令牌。最后,当到期时,他点击身份验证服务器以刷新他的令牌。身份验证服务器在没有管理声明的情况下发出新令牌,用户将无法再访问管理功能。这会创建一个窗口,在此期间用户的声明与服务器不同步。这再次解释了为什么访问令牌应该是短暂的,因此同步可以经常发生。

本质上,您每 15 分钟更新一次授权检查,而不是对每个请求进行检查(这是典型的基于会话的身份验证的工作方式)。如果您想要实时权限而不是每 15 分钟刷新一次,那么JWT 可能不太适合

于 2019-10-22T19:26:27.717 回答