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