访问/刷新令牌混淆
Posted
技术标签:
【中文标题】访问/刷新令牌混淆【英文标题】:Access/Refresh token confusion 【发布时间】:2021-09-10 00:31:56 【问题描述】:我一直在阅读有关此主题的大量内容,并且可以看到使用 JWT 进行身份验证有许多不同的观点和方法。
我的理解如下: 在最简单的形式中,JWT 身份验证机制应该:
-
验证用户名和密码。
创建一个签名的 JWT 访问令牌,其中包含有关用户的信息(取决于应用的需要)。
在响应中发送该令牌。
客户端然后存储令牌(据我了解,对于安全 cookie 或 localStorage 是否更安全存在一些争议),并与每个请求的标头一起发送。
然后服务器可以授权用户使用中间件验证 JWT。没有状态,所有信息都包含在 JWT 中。
假设 JWT 没有过期(或者可能是一个很长的过期日期,可能是几个月),这听起来不错,因为我可以为用户提供很长时间的持久登录状态。据我了解,担心的是,如果 JWT 被盗,它本质上是一张无限制的访问卡和一个巨大的安全漏洞。
这就是刷新令牌进入的地方,服务器会发出刷新令牌和访问令牌(刷新令牌具有长/无限过期和访问令牌短)。
服务器数据库保存某种有效刷新令牌表(因此,如果一个被盗,它可以很容易地失效),并且在发布新的访问令牌时,验证刷新令牌。
这还需要在前端添加某种倒计时机制,以便在访问令牌到期日期之前向服务器发送刷新请求,这样用户就不会被注销。
还有我的问题:
为什么?如果我们经历了为刷新令牌创建数据库表的所有麻烦,为什么不制作一个有效访问令牌表并在需要时使它们无效呢?这比使用刷新令牌更安全吗?
谢谢
【问题讨论】:
【参考方案1】:访问令牌主要不是用来提供额外的安全性,而是提供效率和解耦。
访问令牌的生命周期可能很短——甚至可能不到一分钟——但用于在这段时间内对不同服务的多个请求进行身份验证。这些服务不需要对身份验证数据库进行任何访问,因为它们可以信任访问令牌,直到其到期日期为止;这使它们更快更简单。
例如,如果您正在使用包含大量 AJAX 请求的动态页面,则可能会很快连续运行。这些 AJAX 调用可以实现为无服务器函数(例如 AWS Lambda),也可以实现为不同服务器上不同编程语言的独立脚本,或者您可能只想让它们尽可能高效,并避免任何数据库访问。他们之间唯一需要共享的信息是一个公钥,用于验证他们收到的 JWT 上的签名。
从安全的角度来看,这是一种权衡:一方面,访问权已被撤销的用户的访问令牌仍然可以使用,直到过期为止;另一方面,长寿命刷新令牌的传输量远低于传统会话令牌,因此被拦截的机会更少。
解决您的具体问题:
这还需要在前端添加某种倒计时机制,以便在访问令牌到期日期之前向服务器发送刷新请求,这样用户就不会被注销。
不需要“倒计时”。可以访问这两个令牌的代码在使用它之前只需查看其当前的访问令牌;如果它已过期或即将过期,它会使用刷新令牌请求一个新令牌。然后它会获得一个新的访问令牌,可能还有一个更新的刷新令牌 - 刷新令牌上的到期日期表示用户在自动注销之前可以空闲多长时间。
【讨论】:
【参考方案2】:我们不需要制作访问令牌表,而且保护起来很危险。 我们只需要保存刷新令牌并在表中添加一个有效/无效字段。并将访问令牌和刷新令牌发送到客户端。 客户端使用每个请求的标头发送访问令牌。 服务器可以使用验证 JWT 的中间件授权用户。 一段时间后,访问令牌将过期(访问令牌的过期时间比刷新令牌的过期时间短)。 客户端向服务器发送刷新令牌。 然后客户端将使用刷新令牌获取新的访问令牌(刷新令牌应该重新创建,换句话说,我们只能使用一次刷新令牌,我们必须用新的刷新令牌更新刷新令牌表)。 客户端可以获得新的访问令牌和刷新令牌。
希望对你有帮助。
【讨论】:
以上是关于访问/刷新令牌混淆的主要内容,如果未能解决你的问题,请参考以下文章
Github GraphQL API,硬编码访问令牌有效,试图混淆它没有