如何保护刷新令牌?
如何保护刷新令牌?
我正在使用JWT来验证应用程序的用户。当用户登录时,他们会得到一个访问令牌和一个刷新令牌。为了保证刷新令牌的安全,我不会将其存储在客户端上,而是将其保存在后端与他们的帐户一起,以便不易访问。我对刷新令牌的安全性感到困惑,以下是我在阅读有关如何使用刷新令牌的在线资源时理解的逻辑:
- 验证身份
- 将访问令牌和刷新令牌存储在某处(在我的情况下,将访问令牌存储在前端,将刷新令牌存储在后端)
- 在执行api请求时,在api端验证访问令牌
- 如果访问令牌已过期,则使用刷新令牌生成新的访问令牌和新的刷新令牌,将访问令牌发送回客户端
- 像以前一样存储令牌...并重复
我担心的安全问题是,如果其他人(黑客)获得了访问令牌并将其用于向api发送请求,如果令牌过期了,api将使用刷新令牌获取新的访问令牌和新的刷新令牌,并将至less将访问令牌发送回黑客。
我大约阅读了这篇文章5-6次,还阅读了这篇文章以及关于这个主题的其他文章,它们都说类似这样的话:
确保安全存储刷新令牌,因为它的生命周期很长,访问令牌的生命周期很短,所以并不重要
根据我上面描述的流程,即使访问令牌的生命周期很短,刷新令牌也将用于获取新的访问令牌并永久访问。 我是否有什么遗漏?如果黑客获得了过期的访问令牌,API如何知道是谁发送的请求?它仍会使用刷新令牌发送新的访问令牌。 我应该如何验证发送请求的人?
更新:所以我确实了解到当请求新的访问令牌时,我需要发送刷新令牌、客户端ID和客户端密码。 我对此的问题是,同样的问题,黑客可以向我的API服务器发送请求,服务器从黑客那里获取劫持的访问令牌,它将看到它已经过期,那么它将发送刷新令牌,连同客户端ID /客户端密码(作为环境变量存储)到Auth API并获得新的访问令牌/刷新令牌,这使我们回到了同样的问题。
更新2:关于这个问题的一些有趣的问题:
- 为什么OAuth v2既有访问令牌又有刷新令牌?
- https://security.stackexchange.com/questions/87119/how-secure-are-expiring-tokens-and-refresh-tokens
根据第二个问题和答案,刷新令牌似乎不是一种更安全的维护访问权限的方式,只是因为它更容易检测黑客,因为授权/刷新令牌不断请求并使另一个令牌失效。 这个问题在于,只有两个用户同时尝试访问资源时才会发生这种情况-如果只有黑客在特定时间段内处于活动状态,那么他将无限期地访问原始用户的数据,直到原始用户尝试使用应用程序并访问受保护的资源为止。
有一个很好的文件“面向浏览器的应用程序的OAuth 2.0”,讨论这些应用程序的最佳实践。
我会选择在客户端或服务器上保存令牌。混合它(在服务器上保存刷新令牌和在浏览器上保存访问令牌),你会创建自己的协议以及它自己的漏洞。
如果浏览器应用程序只需要访问其后端的访问令牌,您可以考虑将后端作为OAuth2客户端,获取用户的身份,发出将在浏览器和后端之间保持会话的Cookie的身份验证代码。这比交换、刷新和验证OAuth2令牌要容易得多。
如果您真的想将浏览器应用程序保留为接收令牌的OAuth2客户端,则应使用PKCE扩展(因此在网络缓存和浏览器历史记录中保存的身份验证代码不能用于获取令牌),并在每个新访问令牌中获得新的刷新令牌-请看有关刷新令牌的章节:
授权服务器不应向基于浏览器的应用程序发放刷新令牌。
如果授权服务器决定向基于浏览器的应用程序发放刷新令牌,则每次访问令牌刷新响应时都必须发放新的刷新令牌。这样做可以减轻泄漏的刷新令牌的风险,因为如果攻击者和合法客户端都尝试使用同一刷新令牌,则可以检测到泄漏的刷新令牌。
您的浏览器应用程序可以将其令牌保存在sessionStorage
中以便页面重新加载时使用。
简洁版 (改进用户体验的选择)
- 将短期访问令牌存储在内存中或本地存储中。
- 仅将刷新令牌存储在内存中。
只要用户不进行硬刷新或离开您的网站,他们就可以永久登录。
一般想法
我并不是所有不同令牌、机制和存储最佳实践的细节专家(所以请参考其他文章/专家 - 在下面的评论中,Tim Hardy 对我的发现提出了极好且强有力的反驳) ,但似乎在基于浏览器的应用程序中使用刷新令牌是一个不好的想法。刷新令牌可以在手机/其他设备上安全地存储。你可能可以在浏览器中使用http-only cookie或在内存中存储令牌(见下文) ,但同样,我不确定这种方法的安全性(我并不是说它不安全,我是说我不知道它有多安全)。
改善用户体验
尽管(再次强调)我个人不知道在浏览器存储访问/刷新令牌所涉及的风险的全部范围(除了XSS攻击),但您在这里有几个相对安全的选项。
要么仅将长寿命的访问令牌存储在内存中,要么使用短寿命的访问令牌(内存或本地存储也很安全,因为它是短寿命的)和仅将刷新令牌存储在内存中的组合。这种方法允许用户永久登录,只要他们没有刷新页面或离开。