使用 JWT 进行无状态身份验证:刷新令牌不是无状态的

信息安全 验证 jwt
2021-08-23 19:11:41

在我当前的架构中,我的后端向(移动)客户端发出 JWT。选择 JWT 的主要原因是无状态身份验证,即服务器不需要在会话/数据库中存储数据,这意味着更少的开销和可伸缩性问题。
一个常见的策略是登录用户并返回短暂的 JWT(大约 15 分钟 - 正如我所读),以及用户存储在客户端中的刷新令牌。刷新令牌永不过期,只能撤销。目的是避免通过网络多次发送长期存在的 JWT,并且仅在过期时刷新 JWT;当攻击者获得短期令牌时,攻击时间窗口很短。

问题是,当我仔细想想这个故事时,它似乎充满了漏洞。请帮我澄清一下。

  1. 15 分钟的到期时间意味着一些用户可能会每天通过网络发送刷新令牌 10 次。这可能与某些用户使用常规、短期访问令牌发出请求的频率一样高。因此,刷新令牌的论点似乎值得怀疑。
  2. 如果您质疑 SSL,那么我不知道为什么这么多公司使用基本身份验证。要将 JWT 与刷新令牌一起使用,您可能还是应该使用 HTTPS。
  3. 如果您需要在会话/数据库中存储刷新令牌以便向客户端发出新的 jwt,那么 JWT 有什么好处。在这种情况下,刷新令牌将充当存储在后端的一种密码(尽管我意识到它并不完全相同)。这使得身份验证流程本质上是有状态的,并且似乎完全剥夺了使用 JWT 的好处。此外,15 分钟的短暂有效期意味着您有很多开销,如果有 30 分钟的间隔,几乎每次检查手机时都需要获取刷新的访问令牌。不仅有检查存储的刷新令牌的开销,还需要检查刷新令牌是否被列入黑名单,这意味着另一个性能开销。(编辑:
  4. 刷新令牌需要多次服务器往返:
    • 访问令牌过期时返回 401(资源服务器)。
    • 需要在身份验证服务器上请求新的访问令牌
    • 需要重新发起对资源服务器的请求。

有人可以向我解释我在这里缺少什么吗?

2个回答

对无状态会话令牌的主要批评之一是缺乏安全注销。拥有单独的访问/刷新令牌允许妥协。您可以大大减少数据库访问量,同时具有延迟 15 分钟的安全注销功能。

该设计没有采取任何措施来防止会话劫持,即恶意捕获令牌。只需使用 SSL,它现在无处不在。

您可以小心地减少往返次数。许多客户端 HTTP 库允许您执行主动身份验证,这避免了获得 401 的额外往返。

我同意这不是一个特别明智的设计。无论如何,大多数网站的数据库都很繁重,因此检查每个请求的令牌并不会增加太多开销。虽然访问/刷新令牌的基本概念是安全的,但我担心额外的复杂性会导致实施缺陷。

除非这个问题有其他答案,否则我自己当前的解决方案是评估安全风险与性能之间的权衡问题。

我的主要考虑是将“短期”jwt 访问令牌的时间窗口从 15 分钟增加到一天。
鉴于需要 HTTPS,并且请求仅在内部进行,即令牌不会跨域传播。

这意味着在性能方面,令牌刷新每天只发生一次。从理论上讲,在我的情况下,SSL 应该提供足够的安全性;一天的攻击窗口只是在最初不应该发生的事情之上的一种安全措施。

尽管刷新令牌本质上使身份验证过程有状态,但这可能是可以接受的,因为对资源服务器的大多数请求(在这种情况下是一天以上)仍然使用 jwt.