authentication - 在客户端的哪里存储刷新令牌?
问题描述
我的 SPA 应用程序使用以下架构(来源):
这假设我的客户端应用程序知道刷新令牌,因为如果不存在用户凭据(例如电子邮件/密码),我需要它来请求新的访问令牌。
我的问题:在我的客户端应用程序中,我在哪里存储刷新令牌?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 变量?如果是前者,那我应该把我的访问令牌放在哪里?
非常乐意从熟悉该主题的人那里获得有关如何以最佳方式做到这一点的任何线索。
解决方案
您可以将加密的令牌安全地存储在HttpOnly
cookie 中。
https://medium.com/@sadnub/simple-and-secure-api-authentication-for-spas-e46bcea592ad
如果您担心长期存在的刷新令牌。您可以跳过存储它并且根本不使用它。只需将 Access Token 保存在内存中,并在 Access Token 过期时进行静默登录。
不要使用
Implicit
flow 因为它已经过时了。
SPA 最安全的身份验证方式是使用 PKCE 的授权代码。
一般来说,最好使用基于oidc-client的现有库,而不是自己构建一些东西。
推荐阅读
- c# - 如何在 TRUE 全屏模式下启动 UWP 应用?
- javascript - 如何使用每个函数 jquery 在两个相同的类名上添加一个类?
- java - Search View Recycler View 搜索过滤器在 android 中无法正常工作
- artifactory - 神器升级后用户登录问题(5.5.1->6.23.13)
- python - np.cumsum(input) 的长度比输入数组长——这怎么可能?
- excel - 如何根据来自两个不同 Excel 工作表匹配的两个单元格返回整行?
- javascript - 如何设置 react-multi-select-component 的箭头样式?
- reactjs - 尝试导入错误:“initializeApp”未从“firebase”导出(导入为“firebase”)
- javascript - 如何实现像console.log这样的对象序列化
- python - 如何使用 selenium python 从下面的 HTML 中获取文本属性