我正在使用 JWT 对我的应用程序的用户进行身份验证。当用户登录时,他们会获得访问 token 和刷新 token 。为了保证刷新 token 的安全,我不会将其存储在客户端,而是将其与他们的帐户一起保存在后端,这样就不容易访问。不过,我对刷新 token 的安全性感到困惑,这是我在阅读有关如何使用刷新 token 的在线资源时理解的逻辑:
- 验证
- 在某处存储访问 token +刷新 token (在我的例子中,访问 token 在前端,刷新 token 在后端)
- 执行 API 请求时,验证 API 端的访问 token
- 如果访问 token 已过期,则使用刷新 token 生成新的访问 token +新的刷新 token ,并将访问 token 发送回客户端
- 像以前一样存储 token ...并重复
我担心的安全问题是,如果其他人(黑客)掌握了访问 token ,并用它向 api 发送请求,如果 token 过期,api 将使用刷新 token 来获取新的访问 token + 新的刷新 token ,并至少将访问 token 返回给黑客。
我读到this文章大约看了5-6遍,我读了this几次文章以及有关该主题的其他一些文章,他们都说了类似的内容
make sure to store the refresh token securely because it's long lived, the access_token is short lived so not as big of a deal
但根据我上面描述的流程,访问 token 是否短暂并不重要,刷新 token 将用于获取新的访问 token 并永久访问。
我有什么遗漏的吗?如果黑客掌握了过期的访问 token ,API 如何知道谁在发送请求?它仍然会使用刷新 token 发送新的 token 。我是否应该以某种方式验证谁发送了请求?
<小时/>更新
所以我确实明白,当请求新的访问 token 时,我需要发送刷新 token 、客户端 ID 和客户端 key 。我遇到的问题是,像以前一样,黑客可以向我的 API 服务器发送请求,服务器从黑客那里获取被劫持的访问 token ,它会发现它已过期,因此它将发送刷新 token 以及将 clientID/客户端 key (存储为环境变量)发送到 Auth API 并获取新的访问 token /刷新 token ,这让我们回到了同样的问题。
<小时/>更新2
关于这个主题的一些有趣的问题:
- Why Does OAuth v2 Have Both Access and Refresh Tokens?
- https://security.stackexchange.com/questions/87119/how-secure-are-expiring-tokens-and-refresh-tokens
根据第二个问题和答案,刷新 token 似乎并不是一种更安全的维护访问方式,只是更容易检测到黑客,因为身份验证/刷新 token 不断被请求并使其他 token 无效。问题在于,只有当 2 个用户同时尝试访问资源时才会发生这种情况 - 如果黑客恰好在给定时间段内处于事件状态,他将可以无限制地访问原始用户数据,直到原始用户尝试使用应用程序并访问 protected 资源
最佳答案
TL;DR(改善用户体验的选项)
- 将短期访问 token 存储在内存或本地存储中。
- 将刷新 token 存储在内存中(仅限)
现在,只要用户不进行硬刷新或离开您的网站,他们就可以永远登录。
<小时/>总体想法
我不是不同代币的所有复杂性、其机制和存储最佳实践的专家(因此请参阅有关该主题的其他文章/专家 - Tim Hardy 对我的发现提出了极好的且强有力的反驳下面的评论)但在基于浏览器的应用程序中使用刷新 token 似乎是一个坏主意。刷新 token 可以安全地存储在手机/其他设备上。您可以在浏览器中使用仅 http 的 cookie 或将 token 存储在内存中(请参阅下面的更多内容),但同样,我不确定这种方法的安全性(我并不是说它不安全,我是说我不知道安全性如何)
<小时/>改善用户体验
虽然(再次)我个人不知道在浏览器存储中存储访问/刷新 token 所涉及的全部风险(除了 XSS 攻击), 您在这里有几个相对安全的选择。
要么仅在内存中存储长期访问 token ,要么使用短期访问 token (内存中或本地存储也可能是安全的,因为其生命周期很短)与仅在内存中的刷新 token 的组合内存。这种方法允许用户永远登录,只要他们不刷新页面或离开。
关于oauth-2.0 - 如何保护刷新 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55486341/