为啥刷新令牌对于 SPA 来说被认为是不安全的?

Posted

技术标签:

【中文标题】为啥刷新令牌对于 SPA 来说被认为是不安全的?【英文标题】:Why are Refresh Tokens considered insecure for an SPA?为什么刷新令牌对于 SPA 来说被认为是不安全的? 【发布时间】:2018-08-23 18:06:25 【问题描述】:

我正在阅读 Auth0 网站上有关 Refresh Tokens and SPA 的文档,他们声明 SPA's should not use Refresh Tokens 因为它们无法安全地存储在浏览器中,而是使用静默身份验证来检索新的访问令牌。

单页应用程序(通常实现隐式授权)在任何情况下都不应获得刷新令牌。原因是这条信息的敏感性。您可以将其视为用户凭据,因为刷新令牌允许用户基本上永远保持身份验证。因此,您不能在浏览器中拥有这些信息,它必须安全地存储。

我很困惑。据我了解,检索新访问令牌的唯一方法是向 Auth 服务器提交一个新请求,以及某种形式的 Auth0 会话 cookie 来验证登录用户的身份。收到会话 cookie 后,Auth0然后服务器将能够发出新的访问令牌。

但这与在浏览器或本地存储中使用刷新令牌有何不同?是什么让会话 Cookie 比刷新令牌更安全?为什么在 SPA 中使用刷新令牌是一件坏事?

【问题讨论】:

它说客户端不应该接收刷新令牌,而不是不应该使用它们。它们只是不应该存储在客户端。 至于为什么它是一件坏事......它就在那里说......“刷新令牌允许用户基本上永远保持身份验证。”这就是潜在的不利因素。 【参考方案1】:

好问题 - 所以没有真正安全的方法可以在浏览器上存储任何令牌(或任何其他机密信息) - 请参阅 links such as this。因此,单页应用程序 (SPA) 不应存储刷新令牌 - 刷新令牌尤其成问题,因为它是长期存在的(长期过期或无过期),如果被盗,则攻击者可以在每个单独过期后继续刷新访问令牌.

最好只在需要时检索您的访问令牌(例如调用 API),或者只存储在内存中(仍然容易受到 XSS / CSRF 的攻击),但更好 - 或者使用并忘记。然后在下次需要访问令牌时再次调用 checkSession。

对于您的问题 - checkSession request 不需要发送令牌。顾名思义,它是字面意思 - 针对授权服务器的“检查会话”,以查看会话是否存在。如果是,则授权服务器 响应 将包含一个新的访问令牌。见here for an example usage with SPA

如果有什么需要进一步说明等,请随时在此答案下方留下我的 cmets。

【讨论】:

我仍然不明白为什么会话 cookie 比刷新令牌更好。为了在没有刷新令牌的情况下获得新的访问令牌,我仍然需要提交会话 cookie。为什么这被认为比刷新令牌更好?会话 cookie 与刷新令牌具有相同的问题(长期存在,可用于生成新的访问令牌)。那么为什么使用会话 cookie 被认为是“安全的”而 RT 不是呢? Eric B. 作者遗漏的是,现在您使用的会话 cookie 可以附带防伪令牌。这里有更多关于使用防伪令牌预防 CSRF 的内容。 docs.microsoft.com/en-us/aspnet/web-api/overview/security/… 如何将刷新令牌存储在 cookie 中并正确保护 cookie,例如。 Http 标志集。 如果我将refresh_token加密存储在cookie/server中,并且只在需要时由服务器通过后端生成1分钟的生命周期access_token,是否有意义? (访问其他资源) 会话 cookie 不会永久存储。所以,如果你关闭浏览器,你需要重新登录(输入用户名和密码等)。如果您使用 cookie 进行身份验证,则应使用 OIDC 隐式流(在同意后静默)获取访问令牌以供 REST API 使用。这使您可以将 cookie 和 CSRF 保护限制在您的登录服务器上,这可能与您的 REST 服务的域名不同。例如。 login.example.com 与 api.example.com.【参考方案2】:

在 SPA 中不使用刷新令牌,因为为了使用它 - 并从 /token 获取新的访问令牌,SPA 需要有一个客户端密码,该密码不能安全地存储在浏览器中。但由于OAuth 2.0 for Native Apps RFC 建议不需要/token 端点的客户端密码(对于公共客户端),刷新令牌甚至可以在SPA 中使用。

要获取刷新令牌,您需要使用Auth code grant,它将重定向 URL 中的代码传递到托管 SPA 的服务器(这可能是一个额外的攻击点)。隐式授权仅将令牌传递给浏览器(重定向 URL 的哈希部分不会到达服务器)。

使用刷新令牌和 SSO 会话 cookie 的区别 - cookie 可能更安全,因为它可以标记为 HttpOnly,使其无法被使用 javascript 代码的攻击访问。

更新

使用PKCE 扩展,授权代码流(带有刷新令牌)成为推荐的流,即使对于基于浏览器的应用程序也是如此。详情见最新版OAuth 2.0 for Browser-Based Apps RFC。

【讨论】:

在 PKCE 的情况下,grant_type=refresh_token @ján-Halaša 需要哪些参数 PKCE 定义了三个参数——code_challengecode_challenge_methodcode_verifier,有必要知道它们是如何工作的。如果不将前两个参数用于初始身份验证调用,则不能仅将其用于令牌端点调用。 我已将这些参数用于初始身份验证调用并存储了 code_challenge、code_challenge_method。但我找不到任何有关 refresh_token 调用所需内容的文档,因为我无法为 SPA 发送 client_secret,我不确定需要哪些参数。您是否建议我应该发送 code_verifier 以及 client_id 以更新令牌。 @user606669 你有没有想过如何在初始 /authorize 调用中刷新? @user1110790 我的理解是,一旦你获得了刷新令牌,你所要做的就是发送 refresh_token 和 clientId 以获得一组新的(access_token 和 id_token)【参考方案3】:

关于 cookie 和刷新令牌以及 OAuth2 存在很多误解。

首先,只有机密客户端才能使用刷新令牌是不正确的。 OAuth2 协议规定机密客户端必须进行身份验证,但不需要机密客户端。因此,客户端身份验证在刷新操作中是可选的。见RFC 6749, Section 6, Refreshing An Access Token。

其次,您必须了解替代方案是什么:

    强制用户每 5 分钟输入一次用户名和密码(只要访问令牌过期) 长期访问令牌 通过 HTTP Cookie 进行身份验证

世界上每个不使用刷新令牌的人都使用选项#3。通过 cookie 进行身份验证在功能和安全方面 100% 等同于存储刷新令牌。当然,对于令牌和 cookie,它们的保存位置都有选择:

一个。仅限 HTTP, 湾。安全(需要 TLS/SSL)和 C。会话(内存中)与持久性(本地、域存储)

“仅 HTTP”选项仅适用于 cookie,因此可能代表使用 cookie 优于令牌的唯一优势。 IE。令牌是通过 Javascript 处理的,因此没有办法让它们远离脚本。也就是说,令牌仅对存储它的页面域中的 Javascript 可用(或在 CORS 策略允许的情况下)。所以这个问题可能被夸大了。

当然,必须注意始终使用 TLS/SSL 传输身份验证 cookie 或令牌。老实说,由于我们知道大多数违规行为都发生在私有企业网络内,因此端到端 TLS 不再是一项基本要求。

最后,cookie 或令牌是否一直持久化,即存储在关闭浏览器甚至重启设备后仍然存在的地方,取决于您在可用性和安全性之间做出的权衡 - 您的应用程序。

对于需要更高级别安全性的应用程序,只需将所有内容都保存在内存中(即会话 cookie、Javascript 变量中的令牌)。但是对于不需要太多安全性并且确实需要几天或几周的会话寿命的应用程序,那么您需要存储它们。无论哪种方式,该存储都只能由原始域中的页面和脚本访问,因此,cookie 和令牌在功能上是等效的。

【讨论】:

【参考方案4】:

这不再是真的(2021 年 4 月),Auth0 site 现在声明了不同的事情:

Auth0 建议使用刷新令牌轮换,这为在 SPA 中使用刷新令牌提供了一种安全的方法,同时为最终用户提供对资源的无缝访问,而不会因 ITP 等浏览器隐私技术而导致用户体验中断。

Auth0 之前的指导是在 SPA 中将授权代码流与代码交换证明密钥 (PKCE) 与静默身份验证结合使用。这是一种比隐式流程更安全的解决方案,但不如带有刷新令牌轮换的代码交换证明密钥 (PKCE) 的授权代码流程安全。

请注意在刷新令牌中启用轮换的重要性。

【讨论】:

使用刷新令牌轮换,访问令牌和刷新令牌的生命周期应该是多少?或者什么时候最安全?

以上是关于为啥刷新令牌对于 SPA 来说被认为是不安全的?的主要内容,如果未能解决你的问题,请参考以下文章

在基于令牌的身份验证中使用刷新令牌是不是安全?

刷新令牌如何比长寿命的 JWT 更安全?

我是不是使用刷新令牌?

绕过 XHR 的 CSRF 保护是不是安全? (导轨)

SPA中令牌存储和刷新的选项

SPA 中的令牌存储和刷新选项