为什么要在服务器端存储 JWT 刷新令牌?

时间:2021-03-21 19:00:13

标签: authentication jwt refresh-token

我读过几篇文章(例如 thisthis 以及 this SO answer),这些文章建议将服务器端的刷新令牌存储在数据库或内存中(或内存存储,例如Redis)。据我所知,这是为了撤销它们。

是否有充分的理由按照这些文章的建议存储所有令牌,而不仅仅是在注销时存储列入黑名单的令牌?如果我了解存储令牌的原因,我当然可以通过在 Redis 中存储令牌 ID 来达到相同的效果(只要到期就具有 TTL,这样表就不会变得笨拙)。

这种方法是否有缺点,如果有,它们是什么(或者相反,存储所有令牌与仅存储已撤销令牌列表相比有什么优点?)


为了详细说明,以及为什么我认为有一个撤销列表应该没问题,这是我想象的过程:

  • 发行代币
  • 一旦被撤销(例如,在注销时),将一个条目添加到黑名单以获取具有撤销时间的唯一 ID(例如,public_user_id,如果不同设备有许多令牌),并添加一个 TTL,直到令牌到期
  • 为身份验证提供令牌时,当存在现有黑名单条目时:
    • 如果使用了有效的令牌,它将在它到期之前并且在唯一 id 的黑名单条目创建时间之后有一个创建时间
    • 如果使用了无效的令牌,它将在创建条目之前过期或在具有唯一标识符的黑名单中

我是否遗漏了该流程中需要所有令牌列表的关键内容?

3 个答案:

答案 0 :(得分:1)

拥有所有已发行令牌列表的优点是您可以全面了解谁已经通过身份验证并且当前可以访问系统。然后,您可以根据任何标准(例如,令牌的年龄、与令牌用户关联的角色、IP 地址范围)选择从该列表中撤消某些令牌。

如果您只有一个已撤销令牌的列表,则无法在运行时选择任意条件来撤销有效令牌的子集。换句话说,如果您没有所有已发布令牌的列表,则无法立即在全球范围内强制执行撤销标准,而只能在将令牌提供给资源服务器时执行。

答案 1 :(得分:0)

在我的特定情况下,失效似乎没有任何好处,但这只是因为令牌包含我不需要令牌进行失效的信息。

例如,如果具有 id: 1234 的用户的令牌被撤销,我不需要比撤销信息更多的信息,因为按照惯例,所有令牌都将在其声明中包含标识符。然后我可以创建一个包含撤销时间和用户 ID 的撤销列表,并在解码时检查令牌是否在令牌发布之前具有用户 ID 的撤销条目。

请注意,这仅适用于所有令牌继续具有此约定的情况,并且仅当所有令牌仅通过这些方式无效时;否则,我将需要撤销所有令牌(例如,通过更改令牌机密)并修改该决定。

对于我的用例,我不太可能改变撤销策略,所以我可能会继续只存储撤销。但是,我注意到 JWTs aren't the best 对于我的用例。现在,回到会话!


大编辑:Ron 在评论中指出,要撤销每个刷新令牌,您肯定需要一个令牌列表。废掉上面的

答案 2 :(得分:0)

我在这里的目标是技术简单的方向,因为授权服务器 (AS) 应该为您完成繁重的工作。以下是一些首尾相连的注释,解释了一些棘手的方面并提出了一个简单的方向。

1.代币发行

用户进行身份验证(并可选择同意)导致令牌“授予”。然后,AS 应该为您存储刷新令牌,在一个可能名为“委托”的数据库表中。通常,存储的“令牌”将是散列而不是实际值,并将链接到应用程序 (client_id) 和用户 (subject)。发行的令牌可能具有以下生命周期:

  • 刷新令牌:4 小时
  • 访问令牌:30 分钟

2.令牌刷新

OAuth 客户端(例如移动应用)将在授权或“用户会话”的生命周期内以静默方式更新访问令牌。这涉及向 AS 发送刷新令牌并取回新的访问令牌。为此,AS 需要存储刷新令牌的哈希值,以便能够验证输入。

3.默认删除行为

当用户注销时,令牌会从客户端应用程序中清除,因此它们消失了。较新的 OAuth 2.1 建议是使用轮换刷新令牌,其中每次访问令牌刷新也会更新刷新令牌并使前一个无效。在我们的示例中,这意味着被盗刷新令牌的生命周期可能会缩短 - 可能只有 30 分钟。

4.管理员手动撤销

如果出于某种原因您想明确拒绝对特定用户和应用程序的访问,管理员可以使用 AS 数据库并发出类似这样的命令,尽管管理 UI 可能会提供更多可视化选项。

  • 从 client_id=[value] 和 subject=[value] 的委托中删除

手动撤销是否可以在人员级别进行管理是有问题的,但它是一种很好的能力,例如在安全审查中。

5.注销时撤销刷新令牌

当然,在清除令牌之前,如果需要,客户端可以在注销时撤销自己的刷新令牌。这还应确保授权服务器拒绝相同授权的任何访问令牌。

6.访问令牌有效性

访问令牌是最常见的 JWT。当 JWT 仍有 25 分钟的生存时间时,可能会发生撤销或注销。如果攻击者以某种方式拦截了访问令牌(这通常是不可能的),他们可以继续针对您的 API 使用它 - 在此期间 AS 将永远不会看到访问令牌。

7. API 网关设置

在更复杂的设置中,不透明的访问令牌被颁发给 Internet 客户端,然后发送到 API 网关,API 网关会对它们进行内省,如 Phantom Token Pattern 中所示。网关还维护访问令牌结果的缓存。

在撤销时,AS 可以发出 Custom Event 通知 API 网关,然后 API 网关可以为用户清除任何缓存的访问令牌。这应该确保下一个带有已撤销(或注销)用户的访问令牌的请求被拒绝。

总结

除非您要处理非常安全的域,否则我会以简单为目标并遵循以下两个原则:

  • 将令牌存储和撤销留给授权服务器
  • 保持令牌的短暂性,这样撤销就不会成为问题