jwt 访问令牌和刷新令牌流

Posted

技术标签:

【中文标题】jwt 访问令牌和刷新令牌流【英文标题】:jwt access token and refresh token flow 【发布时间】:2021-08-23 14:47:18 【问题描述】:

这是我的身份验证流程:

    用户登录后收到两个令牌(有过期时间的访问令牌和没有过期时间的刷新令牌) 对于每个用户,刷新令牌存储在数据库中名为 refreshTokens(它是一个数组)的 json 列中。 在客户端,访问令牌和刷新令牌都存储在本地存储中。 当需要验证用户时,如果访问令牌过期,则使用刷新令牌创建新的访问令牌并发回给用户并保持用户登录状态。 当用户注销时,存储在数据库中(在 refreshTokens 列表中)的刷新令牌被删除。

我的问题是:

    这个流程安全吗? 我需要在 cookie 上保存刷新令牌还是本地存储足够好?

【问题讨论】:

为了使其更安全,我确保刷新令牌链接到“设备” - 在移动应用程序上,使用手机 ID 很容易,在浏览器上,这可能更具挑战性 - 例如UA 和 geo/ip 的组合。 【参考方案1】:

该流程取决于 OAuth 的工作方式以及令牌如何以安全的方式存储,因此对这两个问题都表示“是”。缺少的部分首先是如何获得令牌:因为使用 PCKE 的授权代码授权类型是首选方式,而不是传统的隐式授权类型。

【讨论】:

【参考方案2】:

保护此流程的一个重要部分是,在第 4 点中,您使用数据库中保存的刷新令牌列表来验证 RT 未被撤销。除此之外它看起来还可以。您可以通过添加过期时间来刷新令牌来增加安全性。那么,即使用户没有主动注销(你没有从DB中清除RT),RT也会在一段时间后无法使用。

在我看来,将令牌保存在本地存储中就足够了。

【讨论】:

我最近为每个刷新令牌添加了一些过期时间(1 年),为每个访问令牌添加了 10 分钟。但你是说我不需要在数据库中保留刷新令牌?我应该把它们放在哪里? redis 存储可能吗? 不,我的意思是:您将 RT 保存在数据库中,这没关系。因此,当您收到刷新请求时,请确保您不仅验证 RT 的签名(如果它是 JWT),还要将收到的 RT 与您在 DB 中的列表进行比较。只有这样,您的解决方案才是安全的。 您还可以使用短期 RT(例如 4 小时/1 天等),并且每次用户刷新 AT 时,您都会延长 RT(发出新的 RT)。这样您就不必将它们保存在数据库中,并且您知道如果他们在 RT 的到期时间内使用您的网站,用户将被“注销”。 (因为如果用户在那一天没有做任何事情,RT 就会过期)。 我所做的是创建一个访问令牌(有效期为 10 分钟)和一个刷新令牌(有效期为 6 个月),然后当我验证刷新令牌(假设访问已过期)时,首先我验证签名,然后将其与数据库中的 refreshTokens 列表进行比较。

以上是关于jwt 访问令牌和刷新令牌流的主要内容,如果未能解决你的问题,请参考以下文章

JWT 刷新和访问令牌

JWT 访问令牌和刷新令牌安全性

JWT 是不是总是需要访问令牌和刷新令牌?

使用刷新令牌和访问令牌如何比仅使用 1 个 JWT 更“安全”?

如何基于使用 Oauth2 协议的身份验证改进 JWT 访问令牌和刷新令牌?

在 Django REST 框架中使用 JWT 时,刷新令牌和访问令牌存储在哪里?