【发布时间】:2019-12-30 05:15:37
【问题描述】:
我的 SPA 应用程序使用以下架构 (source):
这假设我的客户端应用程序知道刷新令牌,因为如果不存在用户凭据(例如电子邮件/密码),我需要它来请求新的访问令牌。
我的问题:我在哪里存储刷新令牌在我的客户端应用程序中?关于这个主题有很多关于 SO 的问题/答案,但关于刷新令牌的答案并不清楚.
访问令牌和刷新令牌不应存储在本地/会话存储中,因为它们不是任何敏感数据的地方。因此,我会将 访问令牌 存储在 httpOnly cookie 中(即使有 CSRF),无论如何我对资源服务器的大部分请求都需要它。
但是刷新令牌呢?我不能将它存储在 cookie 中,因为 (1) 它会随每个请求一起发送到我的资源服务器,这使得它也容易受到 CSRF 的攻击,并且(2) 它会发送具有相同攻击向量的公开访问/刷新令牌。
我能想到三种解决方案:
1) 将刷新令牌存储在内存中的 JavaScript 变量中,这有两个缺点:
- a) 它容易受到 XSS 攻击(但可能不像本地/会话存储那么明显
- b) 如果用户关闭浏览器选项卡,它会丢失“会话”
尤其是后一个缺点会导致用户体验不佳。
2) 将访问令牌存储在会话存储中并通过Bearer access_token 授权标头将其发送到我的资源服务器。然后我可以使用httpOnly cookie 作为刷新令牌。这有一个我能想到的缺点:
- a) 向资源服务器发出的每个请求都会向 CSRF 公开刷新令牌。
3) 将两个令牌都保存在 httpOnly cookie 中,这有提到的缺点是两个令牌都暴露在相同的攻击向量中。
也许除了我提到的缺点之外,还有其他方法或更多(请告诉我),但最终一切都归结为我在客户端的哪里保存刷新令牌?是httpOnly cookie 还是内存中的 JS 变量?如果是前者,那我应该把我的访问令牌放在哪里?
非常高兴从熟悉该主题的人那里获得有关如何以最佳方式做到这一点的任何线索。
【问题讨论】:
-
提供更多信息。这是 SPA 还是基于服务器的应用程序?
-
在这种情况下,它是一个 SPA。
-
想知道您实施的解决方案是什么?我目前正在使用选项 2,而不用担心 CSRF。刷新令牌在每个 SSR 上都使用并失效。但是,当 SPA 在多个选项卡中打开时,这会导致访问令牌不同步。
标签: authentication cookies oauth oauth-2.0 token