JWT 刷新令牌是否提供更高的安全性?应该把它们存放在哪里?
Do JWT refresh tokens provide more security? Where should one store them?
我很难理解 JWT 刷新令牌比仅使用具有较长生命周期的普通 JWT 访问令牌更安全。我知道通过缩短 JWT 访问令牌的生命周期,它限制了攻击者滥用它的 window 机会。这假设攻击者以某种方式绕过了 HTTPS 的 SSL 层,以便首先获得 JWT 访问令牌。
JWT刷新令牌具体是如何解决这个问题的?一旦访问令牌过期,你就必须转移刷新令牌,如果我们假设HTTPS,它也可以被劫持不够安全。如果攻击者获得了刷新令牌的控制权,那么他现在可以访问大量的访问令牌,因为刷新令牌通常具有很长的生命周期。 推而广之,我们还可以说,如果 HTTPS 协议遭到破坏,初始 username/password 身份验证也可能被盗。
由于刷新令牌必须保存在前端(我正在构建一个 Angular/Spring 启动应用程序),我们必须格外小心,刷新令牌也不能被客户端窃取。 LocalStorage 显然不适合存储刷新令牌,因为它不是安全存储。它们也不适合在每个请求中发送,否则它们会与访问令牌一起被盗,这首先违背了使用短寿命访问令牌的目的。 应该在哪里存储刷新令牌?
如果我想在登录页面提供 记住我 功能,我可以简单地设置无限寿命的刷新令牌吗?
我已经通过以下链接(以及更多)浏览了几个写得很好的答案:
SPA best practices for authentication and session management
https://security.stackexchange.com/questions/119371/is-refreshing-an-expired-jwt-token-a-good-strategy
但是我对这3个问题都不满意
我将尝试回答您问题中的所有要点
不要使用 JWT 刷新令牌。使用不透明的刷新标记。通常,JWT 的生命周期非常短。这样做的原因是,如果您没有黑名单,可能无法撤销它们
您可以将刷新令牌存储在 HttpOnly 安全 cookie 中。如果你想避免 CSRF 和 XSS,那么你可以将 access token 拆分,一半存储在 cookies 中,另一半存储在 localstorage
如果您假设 https 已被破坏(这实际上是可能的),那么这里最好的防御措施是采取措施来检测被盗的刷新令牌。您可以通过实施 rotating refresh tokens 来完成。这也可以用来非常容易地实现记住我的功能,并且具有最高的安全级别。
总的来说,这个话题很复杂,我不可能在这里一一解释。所以这是一个 blog post I like that explain everything todo with session security. They also have an open source library called SuperTokens 你可以使用的,这是迄今为止我见过的最安全的实现。他们在各种技术堆栈中都有它,也可以为您的技术堆栈实现一个。
您已经收到答案并选择了它,但我想我会添加另一个观点。
首先我会指出一些关于您的假设的神话:
LocalStorage is clearly unsuitable to store the refresh token since it
is not meant to be a secure storage.
我敢肯定有些人会不同意我的看法,但对我来说,LocalStorage 与 Cookie 存储一样安全,甚至更多。
Cookie 容易受到 CSRF 攻击,而 LocalStorage 则不那么容易。并且 LocalStorage 和 Cookies 都容易受到 XSS 攻击(甚至是 httpOnly cookies,因为注入的代码可以使用 Credentials 执行任何操作)。
因此从这个角度来看,Cookie 提供了比 LocalStorage 更大的攻击面。
因此,从纯粹的安全角度来看,我认为在 LocalStorage 中存储访问或刷新令牌没有任何问题。
除了安全问题之外,您可能需要将它们存储在 LocalStorage(或 non-Cookie 存储)中,具体取决于您部署到的平台,例如: 一些移动框架不支持 Cookies。
相反,如果您计划 运行 一个执行 server-side 呈现的 JS Web 应用程序,您可能需要 Cookie,因为服务器进程通常无法访问 LocalStorage。
所以问题不完全是安全问题。
关于你提问的主要内容,我理解为:
如果访问令牌容易受到攻击,那么什么使刷新令牌有用,因为它们也一定容易受到相同的攻击?
你是对的。访问令牌和刷新令牌都可能受到损害。问题是...一旦发现,您的服务器可以做什么?
访问令牌和刷新令牌的想法是访问令牌是短暂的而刷新令牌是长期的。
就我个人而言,除非您使用 JWT 作为您的访问令牌,否则我认为刷新令牌几乎没有用处,这是您在 post.
中回避的内容
正如您可能知道的那样,JWT 是无状态的(尽管您可以实现 white/black 列表来使它们有状态,但这有点违背了目的)。因此,服务器无法执行任何操作来禁用无状态 JWT。
由于这个事实,有些人认为 JWT 的过期时间过长是有风险的,因为如果受到威胁,它们不容易被禁用。我同意这一点。
因此,为了获得“两全其美”的效果,可以使用 short-expiry JWT(10 分钟左右)和 long-expiry 刷新令牌(许多 OAuth 实现永远不会使刷新令牌过期)。
此策略允许服务器拒绝颁发新的刷新令牌,从而拒绝新的访问令牌,同时还受益于 JWT 的一些卖点,从而使您的服务器获得一些控制权。
我很难理解 JWT 刷新令牌比仅使用具有较长生命周期的普通 JWT 访问令牌更安全。我知道通过缩短 JWT 访问令牌的生命周期,它限制了攻击者滥用它的 window 机会。这假设攻击者以某种方式绕过了 HTTPS 的 SSL 层,以便首先获得 JWT 访问令牌。
JWT刷新令牌具体是如何解决这个问题的?一旦访问令牌过期,你就必须转移刷新令牌,如果我们假设HTTPS,它也可以被劫持不够安全。如果攻击者获得了刷新令牌的控制权,那么他现在可以访问大量的访问令牌,因为刷新令牌通常具有很长的生命周期。 推而广之,我们还可以说,如果 HTTPS 协议遭到破坏,初始 username/password 身份验证也可能被盗。
由于刷新令牌必须保存在前端(我正在构建一个 Angular/Spring 启动应用程序),我们必须格外小心,刷新令牌也不能被客户端窃取。 LocalStorage 显然不适合存储刷新令牌,因为它不是安全存储。它们也不适合在每个请求中发送,否则它们会与访问令牌一起被盗,这首先违背了使用短寿命访问令牌的目的。 应该在哪里存储刷新令牌?
如果我想在登录页面提供 记住我 功能,我可以简单地设置无限寿命的刷新令牌吗?
我已经通过以下链接(以及更多)浏览了几个写得很好的答案:
但是我对这3个问题都不满意
我将尝试回答您问题中的所有要点
不要使用 JWT 刷新令牌。使用不透明的刷新标记。通常,JWT 的生命周期非常短。这样做的原因是,如果您没有黑名单,可能无法撤销它们
您可以将刷新令牌存储在 HttpOnly 安全 cookie 中。如果你想避免 CSRF 和 XSS,那么你可以将 access token 拆分,一半存储在 cookies 中,另一半存储在 localstorage
如果您假设 https 已被破坏(这实际上是可能的),那么这里最好的防御措施是采取措施来检测被盗的刷新令牌。您可以通过实施 rotating refresh tokens 来完成。这也可以用来非常容易地实现记住我的功能,并且具有最高的安全级别。
总的来说,这个话题很复杂,我不可能在这里一一解释。所以这是一个 blog post I like that explain everything todo with session security. They also have an open source library called SuperTokens 你可以使用的,这是迄今为止我见过的最安全的实现。他们在各种技术堆栈中都有它,也可以为您的技术堆栈实现一个。
您已经收到答案并选择了它,但我想我会添加另一个观点。
首先我会指出一些关于您的假设的神话:
LocalStorage is clearly unsuitable to store the refresh token since it is not meant to be a secure storage.
我敢肯定有些人会不同意我的看法,但对我来说,LocalStorage 与 Cookie 存储一样安全,甚至更多。
Cookie 容易受到 CSRF 攻击,而 LocalStorage 则不那么容易。并且 LocalStorage 和 Cookies 都容易受到 XSS 攻击(甚至是 httpOnly cookies,因为注入的代码可以使用 Credentials 执行任何操作)。
因此从这个角度来看,Cookie 提供了比 LocalStorage 更大的攻击面。
因此,从纯粹的安全角度来看,我认为在 LocalStorage 中存储访问或刷新令牌没有任何问题。
除了安全问题之外,您可能需要将它们存储在 LocalStorage(或 non-Cookie 存储)中,具体取决于您部署到的平台,例如: 一些移动框架不支持 Cookies。
相反,如果您计划 运行 一个执行 server-side 呈现的 JS Web 应用程序,您可能需要 Cookie,因为服务器进程通常无法访问 LocalStorage。
所以问题不完全是安全问题。
关于你提问的主要内容,我理解为:
如果访问令牌容易受到攻击,那么什么使刷新令牌有用,因为它们也一定容易受到相同的攻击?
你是对的。访问令牌和刷新令牌都可能受到损害。问题是...一旦发现,您的服务器可以做什么?
访问令牌和刷新令牌的想法是访问令牌是短暂的而刷新令牌是长期的。
就我个人而言,除非您使用 JWT 作为您的访问令牌,否则我认为刷新令牌几乎没有用处,这是您在 post.
中回避的内容正如您可能知道的那样,JWT 是无状态的(尽管您可以实现 white/black 列表来使它们有状态,但这有点违背了目的)。因此,服务器无法执行任何操作来禁用无状态 JWT。
由于这个事实,有些人认为 JWT 的过期时间过长是有风险的,因为如果受到威胁,它们不容易被禁用。我同意这一点。
因此,为了获得“两全其美”的效果,可以使用 short-expiry JWT(10 分钟左右)和 long-expiry 刷新令牌(许多 OAuth 实现永远不会使刷新令牌过期)。
此策略允许服务器拒绝颁发新的刷新令牌,从而拒绝新的访问令牌,同时还受益于 JWT 的一些卖点,从而使您的服务器获得一些控制权。