使用刷新令牌和访问令牌如何比仅使用 1 个 JWT 更多 'secure'?

How can both using refresh- and access tokens be more 'secure' than just using 1 JWT?

与仅使用 1 个 JWT 令牌相比,同时具有刷新和访问令牌的系统 'safer' 有何不同?

据我所知,在第一种情况下,如果刷新令牌有效,服务器将使用访问令牌进行响应(如果前一个令牌尚未过期,则不会)。在这种情况下,当中间人窃取访问令牌时,他们使用它的时间将非常有限(因为它们通常是短暂的)。

但是:如果中间人窃取刷新令牌,只要刷新令牌有效,他仍然可以请求新的访问令牌。

因为通常刷新和访问令牌都存储在例如cookie 或 localStorage;这个概念比只使用 1 个 JWT 更安全吗?

--

我可能在这里遗漏了一些非常简单的东西,但我就是无法理解它。除了能够控制 'session' 即刷新令牌有效性(因为它存储在 memory/DB 中),我看不到这样做的好处。

您可能感到困惑,因为您不需要整个 JWT 东西。在您的场景中,也许一个普通的旧会话 ID 就足够了并且会更安全。 JWT 不是圣杯,而且被过度使用了。

只有以不同的方式存储刷新令牌和访问令牌才有意义。将它们都放在同源的 localStorage 中(几乎)没有意义,您可以只使用寿命更长的访问令牌,仅此而已。

但这不是重点。在那种情况下,您甚至不需要 JWT。

在典型的场景中,通常有一个身份提供者,一个“登录服务器”,如果你喜欢的话,它会颁发令牌。这与资源服务器(有时很容易混淆地称为客户端)不同,后者实际上是您的后端应用程序。发生的事情是您将未经身份验证的用户发送给身份提供者,例如 example-idp.com。他们在 example-idp.com 上进行身份验证(登录)并建立某种会话,例如通过在 httpOnly cookie 中设置刷新令牌 for example-idp.com。然后您的用户被重定向到您的应用程序,该应用程序直接接收访问令牌或某种可以交换访问令牌的代码。无论哪种方式,访问令牌都将为应用程序来源存储,即。示例-app.com。这可以是一个 cookie,但它通常存储在 localStorage 中。原因是可能有多个应用程序(example-app1.com 和 example-app2.com),javascript 客户端必须向其发送相同的令牌,但它无法做到如果它存储在 httpOnly cookie 中(尽管这对 XSS 是安全的)。

这样做的好处是,即使 example-app.com 遭到破坏(通过 XSS)并且攻击者破坏了一个短期访问令牌,他们仍然无法获得对刷新令牌的访问权限,因为这是为不同的来源设置的,并且可能作为 httpOnly cookie。虽然访问令牌仍然有用,但 XSS 需要受害者用户交互(即用户必须对 运行 攻击者的 javascript 做一些事情),因此攻击者可能很难获得新的一旦旧的过期。

所以简而言之,如果您没有所有这些复杂性,并且只有一个普通的服务器端应用程序和从同一来源下载的 javascript 客户端,则您不需要任何令牌或 JWT,最安全的选项是正确实现的普通旧会话 ID。您可能会争辩说 JWT 是无状态的,但大多数应用程序根本不需要是无状态的(如果您需要令牌撤销,它也不能是无状态的)。如果您的应用程序确实需要无状态,并且您将以与访问令牌完全相同的方式存储刷新令牌,则可以不使用刷新令牌 - 但请在设置到期前评估风险。

你真正需要访问令牌的复杂性,通过刷新令牌等更新的通常是单点登录场景,或者如果你实现不同的存储(例如,不同的来源,httpOnly 与 javascript -accesisble) 用于不同的令牌。

关于为什么两个代币比一个更好,还有更多要说的。

JWT 令牌旨在不仅与一台服务器通信,而且与许多服务器通信。这种情况以指数方式增加了攻击面,因为您与之交谈的每台服务器都有可能暴露您的访问令牌并破坏您帐户的安全性。这不仅仅是客户端安全的问题,无论您是否将两个令牌保存在本地存储中。服务器也需要受到保护,并且短期访问令牌可以减轻风险,例如通过服务器上错误配置的日志处理暴露您的访问令牌。

将访问令牌视为脏令牌,或用于完成任务的令牌。刷新令牌是一个干净的令牌。仅在需要与身份验证服务器通信时才使用令牌。