JWT 刷新令牌的全部意义是啥?
Posted
技术标签:
【中文标题】JWT 刷新令牌的全部意义是啥?【英文标题】:What's the whole point of a JWT refresh token?JWT 刷新令牌的全部意义是什么? 【发布时间】:2021-12-16 08:55:08 【问题描述】:我已经阅读了一段时间,没有任何意义,而且解释相互矛盾,而 cmets 正在证明这一点。
到目前为止,我的理解是 JWT 存储由服务器编码的信息,可能有到期时间,如果信息有效,服务器及其密钥可以解码其中的信息。有道理。
它对于可扩展性很有用,因此独立的 API 可以解码和验证令牌中的信息,只要它们具有密钥。此外,不需要将信息存储在任何数据库中,不像在会话中那样。有道理。
如果令牌被盗,API 无法判断令牌是否被正确的人使用。这是上述的缺点。
通过缩短代币的到期时间,可以减少安全漏洞,让窃贼在未经许可的情况下使用代币的时间更少。 (附带问题,但如果他们能偷一次,他们可能也会偷第二次)
但是减少令牌有效期的时间意味着每次令牌过期时用户都需要登录,并且从上面看,它非常频繁,因此不会提供太好的用户体验。有道理。
从现在开始,一切都没有意义了:
引入刷新令牌可以解决这个问题,因为它有更长的到期时间。使用刷新令牌可以生成访问令牌,因此用户只要拥有刷新令牌就可以登录 - 这是一段较长的时间 - 而被盗的访问令牌仍然只在短时间内有效。
对我来说,以上似乎是额外的复杂层,而安全性没有任何改进。 IE。对我来说,上面似乎等于一个长期存在的访问令牌。
为什么?因为对我来说,刷新令牌似乎基本上是一个访问令牌(因为这是它生成的)。因此,拥有刷新令牌意味着无限的访问令牌,因此对 API 的无限访问。
然后我读到一个答案,刷新令牌和访问令牌是一对一的映射,所以窃取访问令牌仍然意味着对 API 的未经授权的访问,但只是在很短的时间内,并且窃取了刷新令牌会生成不同的访问令牌,因此 API 可以检测到异常(同一帐户使用不同的访问令牌),从而使访问令牌无效。
看来我不是唯一一个对这个问题感到困惑的人。
如果上述情况不成立,那么刷新令牌究竟有什么帮助?
如果上述情况属实,并且确实存在刷新令牌和访问令牌的一对一映射:
它完全失去了“无国籍”的好处 用户无法从多个设备登录(这将是一个“异常”) 我无法理解访问令牌如何失效 - 令牌数据中是否存储了会话 ID,或者用户被“阻止”?如果有人能把问题弄清楚就太好了,因为从5个解释中,有5个相互矛盾的陈述(有时相同的解释包含相互矛盾的信息),许多开发人员都想了解这种方法。
【问题讨论】:
【参考方案1】:关于基于令牌的身份验证存在这种普遍的混淆,所以让我们尝试解决其中的一些问题。
首先,JWT 不只是由服务器“编码”,它们是“签名”的(更准确地说,通常是消息身份验证)。目的是这样的令牌不能被客户端更改或更改,令牌中的任何字段(声明)都可以被信任为颁发者创建它,否则验证将失败。
这产生了两个重要的结论:
验证令牌在任何实现中都很重要(显然) JWT 的内容(声明)未加密,即。这不是秘密,客户可以查看如果此类令牌包含主题的某种身份(用户,如用户 ID 或电子邮件地址)和过期时间,则可以使用此类令牌来维护没有服务器端状态的会话。
另一个重要的收获:
无法以无状态方式注销(立即会话失效),这是一个缺点。为了能够在使现有会话无效的情况下注销,服务器必须存储并检查已撤销的令牌,这必然是一个有状态的操作。此外,JWT 令牌通常以客户端代码 (javascript) 可访问的方式存储,因此客户端应用程序可以读取用户是谁以及令牌何时到期等信息。不必如此,但大多数实现都会这样做,例如。将其存储在本地存储中。这使得这些令牌容易受到 XSS 攻击,这意味着任何成功的 XSS 都将能够获得令牌。
由于到目前为止所讨论的原因,JWT 身份验证本质上不如普通的旧会话安全,并且只应在需要时使用。很多时候使用token auth的时候,其实并没有什么必要,随便看看就行了。
有时这样的令牌存储在 httpOnly cookie 中,但在这种情况下,令牌不能发送到多个来源(localStorage 的一个好处),并且也可以使用普通的旧会话 ID,实际上会更安全.
好的,那么什么是刷新令牌。正如您正确指出的那样,限制访问令牌的生命周期对于限制受损令牌的有效性很有用。因此,当旧的访问令牌过期时,可以使用刷新令牌来获取新的访问令牌。关键是它们的存储位置。
关键要点:
如果刷新令牌的存储方式与访问令牌相同,则通常没有任何意义。这是实现中的常见错误。在更好的架构中,可能会发生以下情况:
至少有两个独立的组件(逻辑上和“物理上”)至少有两个独立的组件:身份提供者(IdP,或“登录服务”)和资源服务器(例如,一个API)。 当用户登录时,他们实际上创建了一个与 IdP 的会话。在这种情况下,为 IdP 来源(域名)设置了普通的旧会话 ID(充当刷新令牌)或实际的 JWT 刷新令牌。 然后在需要时为资源服务器源创建访问令牌,使用与身份提供者的现有会话。 现在即使资源服务器完全被攻破,比如 XSS 成功的情况下,刷新令牌属于完全独立的来源,因此攻击者无法访问。即使来源相同,但刷新令牌位于 httpOnly cookie 中,这也会有所帮助,因为攻击者需要能够对受害用户执行重复的 XSS 以接收新的访问令牌。可以有这方面的实现变体,但重点是上面,对两个令牌的访问分离。
如您所述,刷新令牌与访问令牌的一对一映射我认为这是不寻常且不必要的,但实际上每个用户一个会话有时是必需的(尤其是在您希望拥有用户所做的非常清晰的审计跟踪)。但这与上面讨论的事情没有太大关系。
同样如上所述,正确的注销(会话失效)在无状态的方式下是不可能的。幸运的是,实际上很少有应用程序需要在服务器端实现真正的无状态。
【讨论】:
对我来说,基于上述基于会话的身份验证在各个方面都更有意义(刷新令牌流似乎与会话非常相似)。我正在使用 websockets,并且验证无状态令牌对它们来说是相当痛苦的,因为我在每次访问令牌替换时都重新连接到它们,因为我只能在建立连接时验证 httpOnly cookie 中的令牌。使用会话,我可以扩展每个请求的会话有效性,并在 websocket 上发送消息之前查询它是否仍然有效。你有什么想法? 对于那个用例,普通的旧会话也更简单、更安全。当您需要 SSO、不同于资源服务器的身份服务器或多个资源服务器时,令牌会发挥作用。对于更简单的场景,您通常不需要 JWT。以上是关于JWT 刷新令牌的全部意义是啥?的主要内容,如果未能解决你的问题,请参考以下文章