oauth-2.0 - Light-OAuth2 刷新令牌永远存在?(必须明确删除)
问题描述
我有一个关于light-oauth2刷新令牌的问题。似乎它们永远不会过期,因此必须手动撤销,这会导致 IMO 维护和安全问题,并且似乎也与 light-oauth2 文档相矛盾。
(注意:我对这种行为的解释持开放态度,因为它背后可能有很好的理由。这对我来说只是(目前)违反直觉。)
更多细节
刷新令牌在 refresh_token 表中无限累积。CacheStartupHookProvider中似乎没有任何代码为它们提供 TTL。如您所见,似乎在 1 天后驱逐刷新令牌的代码已被注释掉(第 108-119 行):
// fresh token map with near cache and evict. A new refresh token will
// be generated each time refresh token is used. This token only lives
// for 1 day and it will be removed from the cache automatically.
MapConfig tokenConfig = new MapConfig();
tokenConfig.setName("tokens");
NearCacheConfig tokenCacheConfig = new NearCacheConfig();
/*
tokenCacheConfig.setTimeToLiveSeconds(24 * 60 * 60 * 1000); // 1 hour TTL
tokenCacheConfig.setMaxIdleSeconds(24 * 60 * 60 * 1000); // 30 minutes max idle seconds
tokenCacheConfig.setInMemoryFormat(InMemoryFormat.OBJECT);
tokenCacheConfig.setCacheLocalEntries(true); // this enables the local
*/
此外,light-oauth2 文档指出:
“授权服务器发出新的刷新令牌,客户端必须丢弃旧的刷新令牌并用新的刷新令牌替换它。授权服务器在向客户端发出新的刷新令牌后撤销旧的刷新令牌。 ” (强调我的)
但我自己的测试表明这并没有发生。例如:
- 调用 light-oauth2 代码服务 (GET),并使用发送到重定向 uri 的授权代码。
- 使用授权码调用light-oauth2(POST:授权码授权类型)。它将返回一个授权令牌 T1 和一个刷新令牌 R1。
- 使用刷新令牌 R1调用 light-oauth2 令牌服务(POST:刷新令牌授予类型)。它将返回一个授权令牌 T2 并刷新令牌 R2。
- 使用刷新令牌 R1再次调用 light-oauth2 令牌服务(同样是 POST:刷新令牌授予类型)。它将返回一个授权令牌 T3 并刷新令牌 R3。
第 4 步似乎与文档相矛盾,文档说授权服务器在向客户端发出新的刷新令牌后撤销旧的刷新令牌。然而,从上面的步骤 4 来看,即使在新的刷新令牌 R2 已经发布之后,刷新令牌 R1 似乎也没有被撤销。R1 仍然能够获得新的授权令牌。
所以现在,R1、R2 和 R3 都可以用来获取新的授权令牌,并且可用的刷新令牌集不断增长。
我的问题是这是遗漏还是设计使然(也许应该更新文档)。如果是设计使然,这样做的理由是什么?在我看来
- 发行这么多永不过期的刷新令牌是不安全的
- 它创建了一个维护复杂性,必须手动从数据库中删除刷新令牌,而不是让它们自动过期并被驱逐。
- 向数据库添加这么多新的刷新令牌会更慢并且似乎没有必要(例如:为什么每次发布新的授权令牌时都需要新的刷新令牌?如果仅在授权代码授予中发布新的刷新令牌似乎更有效类型)
谢谢你的帮助
解决方案
这些都是很好的问题,我认为您已经确定了实施中的缺陷。
首先,让我解释一下为什么我们每次使用旧的刷新令牌时都会发出一个新的刷新令牌。
众所周知,我们发行的访问令牌是 JWT 令牌,一旦发行就无法撤销。为了降低访问令牌被盗的风险,我们必须确保访问权限在短时间内过期。通常,根据实施情况在 5 分钟到 15 分钟之间。这就是刷新令牌出现的地方。它可以持续更长时间,并且大多数 OAuth 2.0 实现都提供了一个 API,可以在报告刷新令牌从用户那里被盗时撤销它。根据 Web 应用程序的安全级别,有时刷新令牌需要持续 24 小时到几个月。我们不想限制它,所以我们删除了刷新令牌的 TTL,这样它就永远不会过期。为了最大限度地提高安全性,我们不想一次又一次地重复使用刷新令牌,所以一个新的刷新令牌与访问令牌一起发出。这使得刷新令牌成为一次性令牌,因此一旦被盗,它就不会持续足够长的时间,因为除非应用程序关闭,否则活动会话必须每 5 到 15 分钟更新一次访问令牌。
您发现之前的刷新令牌仍然可以用于获取访问令牌很奇怪,这可能是一个缺陷。如果你看这行代码https://github.com/networknt/light-oauth2/blob/master/token/src/main/java/com/networknt/oauth/token/handler/Oauth2TokenPostHandler.java#L393
旧的刷新令牌将从数据库和缓存中删除。我不知道 Hazelcast 是否会更长时间地缓存数据。对于这个问题,我们需要更多的测试和调查。你能在 light-oauth2 repo 上打开一个问题吗?
由于这是关于安全性,我们需要更多地关注所有细节。让我们解决这个问题并一起修复它。非常感谢您提出这个问题。
推荐阅读
- c - 查找在 ELF 文件中使用符号的用户
- verilog - 可以在systemverilog中的generate for loop内部使用动态数组吗
- c# - 一种在 ASP.NET Core 中的集成测试,使用 EF 和 AutoMapper
- python - 使用python中fuzzywuzzy中的extractOne()与字符串列表匹配的错误字符串
- dart - 在 Flutter 中创建圆形缓存图像
- c# - 在调试器快照中隐藏敏感数据
- javascript - undefined 不是对象(评估“this.props.navigation”)
- r - jupyter中的r图-无法启动png()设备
- react-native - React Navigation - 如何在屏幕之间重复传递数据?
- path - Windows 8.1 中意外删除的路径变量