使用超级令牌进行有效的会话管理
在上一篇文章中,我们了解了会话管理的基础知识。我们还探讨了两种类型的访问令牌,以及它们在提供强大的安全性和良好的用户体验方面各自的不足之处。
在本文中,我们将研究开源库Supertokens及其为加强授权流程所带来的改进。
在此之前,让我们先定义一下理想的系统是什么样的。
理想的会话管理系统
正如上一篇文章所讨论的,我们将根据可扩展性、安全性和用户体验提出建议。
用户体验
- 作为用户,我不希望每次访问页面时都登录。事实上,我也不想长时间登录。
- 想象一下,看完每一集后都要登录 Netflix。这可不是什么好的体验。
- 为了实现这一点,用户应该长期持有访问令牌 - 通常是几天或几周。
- 访问令牌需要较长的有效期。
可扩展性
- 服务器应该能够根据需要扩展,而不受授权过程的阻碍。
- 我们从参考令牌的分析中得到的指导原则是,尽可能避免与服务器端存储的交互。
- 这意味着价值代币具有很好的可扩展性。
安全
- 安全是最重要的,因此,在我们努力提供良好的用户体验和可扩展性的同时,我们不能在安全性上妥协。
- 牢记提供长期有效期和使用 JWT 等价值令牌的目标,让我们看看这种设置的安全性考虑因素。
长期 JWT 的安全问题
我们将 JWT 保存在客户端。这意味着我们无法控制其安全性和被盗风险。参考令牌也是如此。因此,我们需要做好应对令牌被盗情况的准备。
- 如果令牌的有效期过长,攻击者就可以长期使用它来访问资源。有效期过长 = 长期攻击
- 应用程序很难检测请求是来自攻击者还是受害者。可以使用 IP/位置跟踪等算法,但它们效率低下,并且可能导致大量误报和漏报,从而分别导致安全性降低和用户体验恶化。
- 即使万一被检测到,应用程序也很难使 JWT 失效。JWT 本身包含验证信息,应用程序始终会认为其有效。一种可行的方法是将强制失效的 JWT 存储在存储中,直到它们自然过期,并在每次请求时检查其有效性。——性能问题!
刷新令牌的兴起
这引出了刷新令牌的概念。刷新令牌用于在用户的访问令牌已过期或即将过期时延长用户的会话。
在 Supertokens 实现中,刷新令牌是长期参考令牌,它引用存储在服务器端的记录。
这使得应用程序可以跟踪每个用户的活动会话和设备数量。同时,如果用户注销或我们因某种原因需要使用户的会话过期,则很容易使刷新令牌失效。
刷新令牌允许我们使用短期访问令牌。这样一来,访问令牌被盗以及随后的长期攻击相关的问题就得到了缓解。
然而,刷新令牌本身并不能完全避免被盗。但与访问令牌不同,我们将它们存储在后端。我们可以将它们绑定到单个会话,并在需要时使其失效。让我们看看 Supertokens 是如何实现这一点的。
使用轮换刷新令牌加强安全性
- 由于刷新令牌可能被盗,如果我们在每次刷新请求时轮换刷新令牌会怎样?
- 这意味着每当使用刷新令牌时,新的刷新令牌就会在客户端取代它。
身份验证和授权
- 用户向服务器进行身份验证,
- 服务器返回一个访问令牌(30 分钟后过期)和一个刷新令牌(假设 30 天后过期)
- 客户端可以在其请求中继续使用访问令牌 30 分钟。
会话刷新
- 如果访问令牌已过期,客户端将使用现有的刷新令牌向服务器请求另一个访问令牌。
- 服务器返回一个新的访问令牌和一个新的刷新令牌。
- 客户端可以在其请求中继续使用新的访问令牌 30 分钟。
- 等等。
这在代币盗窃时有何帮助?
我们发现单个访问令牌存在两个问题——我们无法检测到盗窃并且无法使令牌无效。
让我们看看 Supertokens 如何使用旋转刷新令牌实现这一点。
盗窃检测和失效
- 刷新令牌 RT0 被盗,访问令牌 AT0 也随之被盗。
- 攻击者使用访问令牌一段时间,然后向服务器请求新的访问令牌。
- 服务器返回一个新的访问令牌 AT1 和一个新的刷新令牌 RT1,使用后将使旧令牌 RT0 无效。
- 与此同时,或者在此之后,受害者还使用旧的刷新令牌 RT0 向服务器请求新的访问令牌。
- 此时,服务器可以检测到刷新令牌被盗。服务器将使与该会话对应的所有刷新令牌失效。
- 这意味着受害者和攻击者都必须重新进行身份验证。
强制刷新
- 在上面的流程中,攻击者在刷新访问令牌之前仍然可以使用一段时间。为了解决这个问题,我们可以强制攻击者在访问令牌被盗后立即刷新它。
- 为此,我们可以使用旧的 IP 跟踪方法。
- 在创建令牌时,我们可以将用户设备的 IP 地址存储在其中。
- 每当我们收到用户的请求时,我们都可以检查请求的IP地址是否与令牌中的IP地址相同。
- 如果 IP 不同,例如攻击者的情况,我们可以要求客户端刷新访问令牌。
- 这将迫使攻击者在访问令牌被盗后立即刷新访问令牌,并进一步缩短攻击者使用被盗访问令牌的时间窗口。
等一下!我们不是说过 IP 追踪效率低吗?——是的!但我们仍然可以使用它。
让我们来谈谈之前阻碍我们进步的低效率因素:
- 误报会导致安全性降低- 如果应用程序无法检测到 IP 地址的变化,或者攻击者能够以某种方式发送与受害者相同的 IP,那么这仍然是一个问题,但这种情况不太可能发生,即使错过了,我们也已经通过减少访问令牌的有效期(对于数学家来说,减少了 1440 倍)使问题变得更小。
- 误报会导致用户重新登录——如果应用程序检测到用户机器本身的 IP 发生变化(例如,当我切换到 VPN 时,我的 IP 发生了变化),它会要求客户端刷新访问令牌。现在这对用户来说不再是问题,因为刷新可以自动进行。
这如何改善流程?
让我们比较一下 Supertokens 的实现与我们上面定义的理想流程相比如何。
用户体验改进
- 会话时间保持不变- 如果我们之前有一个 30 天有效的访问令牌,我们将把它更改为 30 分钟有效的访问令牌和 30 天有效的刷新令牌。这意味着用户在 30 天内仍然不需要登录。
- 现在,还可以帮助用户在新设备登录时查看其登录活动。该库不直接提供此功能,但包含一些 API 来帮助您实现此功能。
- 它还可以实现按需会话撤销。想象一下,如果用户怀疑密码被盗,可以为他们提供注销所有活动会话并更改密码的功能。这同样需要您自定义实现。
注意- 在这两种自定义实现中,您的前端只需要调用库已经为您公开的 API。
可扩展性几乎保持不变
- 虽然刷新令牌存储在服务器端,但每个用户会话每 30 分钟最多检查一次。这对应用程序吞吐量的影响微不足道。
- 平均每次会话有数百个请求(持续时间 <= 30 分钟)。
- 这意味着,当我们引入刷新令牌时,损失率不到 1%。
安全性提高
现在我们来分析一下访问令牌的安全问题是否解决了。
- 较短的有效期意味着攻击者无法长时间使用 JWT。
- 检测——我们现在可以使用如上所述的旋转刷新令牌来检测盗窃。
- 失效 - 在单个 JWT 系统中,无法针对每个用户或每个会话进行失效。但是,现在每个用户会话都有自己的刷新令牌。我们可以根据需要撤销单个会话,而不会影响其他会话。
结论
在本文中,我们将探讨 Supertokens 如何实现会话管理。我们讨论了之前阻碍我们实现会话管理的低效率问题以及现在的解决方案。
如果您想尝试该库,可以从这里开始。Supertokens 提供了详细的实施指南(方案),您可以使用它在一小时内集成和部署您的身份验证/授权系统。
此外,您还可以在几分钟内免费实现社交登录和无密码身份验证等高级功能。
感谢阅读!
文章来源:https://dev.to/abh1navv/ effective-session-management-using-supertokens-2h71