【问题标题】:Do JWT refresh tokens provide more security? Where should one store them?JWT 刷新令牌是否提供更高的安全性?应该将它们存放在哪里?
【发布时间】:2019-11-05 05:43:39
【问题描述】:

我很难理解 JWT 刷新令牌如何比仅使用具有较长生命周期的普通 JWT 访问令牌更安全。我知道,通过缩短 JWT 访问令牌的生命周期,可以限制攻击者滥用它的机会之窗。这假设攻击者以某种方式绕过了 HTTPS 的 SSL 层,以便首先获得 JWT 访问令牌。

JWT 刷新令牌究竟是如何解决这个问题的? 一旦访问令牌过期,你将不得不传输刷新令牌,如果我们假设 HTTPS 不够安全,也可能被劫持。如果攻击者获得了刷新令牌的控制权,那么他现在可以访问大量的访问令牌,因为刷新令牌通常具有较长的生命周期。 通过扩展,我们也可以说,如果 HTTPS 协议被破坏,初始用户名/密码身份验证可能会被窃取。

由于刷新令牌必须保存在前端(我正在构建一个 Angular/Spring 启动应用程序),我们必须特别注意刷新令牌也不能被客户端窃取。 LocalStorage 显然不适合存储刷新令牌,因为它不是安全存储。它们也不适合发送每个请求,因为否则它们将与访问令牌一起被盗,这首先违背了拥有短寿命访问令牌的目的。 应该在哪里存储刷新令牌?

如果我希望在登录页面提供 remember-me 功能,我可以简单地将刷新令牌设置为无限寿命吗?

我已经通过以下链接(以及更多)阅读了几个写得很好的答案:

What if JWT is stolen? SPA best practices for authentication and session management https://security.stackexchange.com/questions/119371/is-refreshing-an-expired-jwt-token-a-good-strategy

但我对这三个问题并不满意。

【问题讨论】:

    标签: jwt jwt-auth


    【解决方案1】:

    我将尝试回答您问题中的所有要点

    • 不要使用 JWT 刷新令牌。使用不透明刷新令牌。通常,JWT 的生命周期非常短。这样做的原因是,如果您没有列入黑名单,可能无法撤销它们

    • 您可以将刷新令牌存储在 HttpOnly 安全 cookie 中。如果你想避免 CSRF 和 XSS,那么你可以拆分访问令牌并将一半存储在 cookie 中,另一半存储在 localstorage 中

    • 如果您假设 https 已被入侵(这实际上是可能的),那么最好的防御措施是采取措施检测被盗的刷新令牌。你可以通过实现rotating refresh tokens来做到这一点。这也可以用来非常轻松地实现记住我的功能,并且具有最高级别的安全性。

    总的来说,这个话题相当复杂,我不可能在这里解释所有内容。所以这里有一个blog post 我喜欢它解释与会话安全有关的所有事情。他们还有一个名为SuperTokens 的开源库,你可以使用它,这是迄今为止我见过的最安全的实现。他们在各种技术堆栈中都有它,也可以为您的技术堆栈实现一个。

    【讨论】:

    • 我喜欢您将访问令牌拆分为 cookie 存储和 localStorage 以缓解 CSRF 和 XSS 的想法。但这如何回答 OP 关于刷新令牌的问题?
    • 谢谢!我相信我已经回答了 OP 的问题(因此被接受了)。 CSRF 的东西只是为了让答案变得完整。
    【解决方案2】:

    您已经收到答案并选择了它,但我想我会添加另一个观点。

    我将首先用你的一个假设指出一些神话:

    LocalStorage 显然不适合存储刷新令牌,因为它 并不意味着是一个安全的存储。

    我相信有些人会不同意我的观点,但对我来说,LocalStorage 与 Cookie 存储一样安全,甚至更多。

    Cookie 容易受到 CSRF 攻击,而 LocalStorage 则不然。并且 LocalStorage 和 Cookie 都容易受到 XSS 攻击(甚至是 httpOnly cookie,因为注入的代码可以使用凭据执行任何操作)。

    因此,从这个角度来看,Cookie 提供了比 LocalStorage 更大的攻击面。

    因此,从纯粹的安全角度来看,我认为在 LocalStorage 中存储访问 NOR 刷新令牌没有任何问题。

    除了安全问题,您可能需要将它们存储在 LocalStorage(或非 Cookie 存储)中,具体取决于您部署到的平台,例如:某些移动框架不支持 Cookie。

    相反,如果您计划运行一个执行服务器端渲染的 JS Web 应用程序,您可能需要 Cookie,因为通常服务器进程将无权访问 LocalStorage。

    所以问题不完全是安全问题。

    至于你问题的主要要点,我的理解是:

    如果访问令牌容易受到攻击,那么刷新令牌有什么用处,因为它们也必须容易受到同样的攻击?

    你是对的。访问令牌和刷新令牌都可能被破坏。问题是......一旦发现它,您的服务器会怎么做?

    访问令牌和刷新令牌的想法是访问令牌是短暂的,而刷新令牌是长期存在的。

    就个人而言,我认为刷新令牌几乎没有用处,除非您使用 JWT 作为访问令牌,而这是您在帖子中没有提到的。

    您可能知道,JWT 是无状态的(尽管您可以实现使它们有状态的白/黑名单,但这有点违背目的)。因此,服务器无法禁用无状态 JWT。

    由于这一事实,一些人认为 JWT 的长期到期是有风险的,因为它们一旦受到损害就不容易被禁用。我同意这一点。

    因此,为了获得“两全其美”的效果,可以使用短期到期的 JWT(10 分钟左右)和长期到期的刷新令牌(许多 OAuth 实现永远不会使刷新令牌过期)。

    此策略允许服务器拒绝发布新的刷新令牌,从而拒绝新的访问令牌,从而使您的服务器获得一些控制权,同时还受益于 JWT 的一些卖点。

    【讨论】:

    • 感谢您写出如此详细的解释!不久前我问过这个问题,经过更多研究,我得出了相同的结论:刷新令牌并没有在某种程度上受到更多的保护以免受攻击,但它们将控制权交还给了服务器。我们不同意 LocalStorage 的使用,但这是另一个话题。 :)
    猜你喜欢
    • 2018-07-19
    • 2020-08-22
    • 2019-02-25
    • 2019-04-25
    • 2017-12-25
    • 2018-10-16
    • 2017-06-02
    • 2013-02-17
    相关资源
    最近更新 更多