OAuth2:是否应该在收到新的访问令牌后使刷新令牌失效?

OAuth2: Should a refresh token be invalidated after receiving a new access token?

我目前正在开发一个遗留应用程序,该应用程序有点松散地实现了 OAuth2 流程。简而言之,当用户使用 username/password 登录时,他会收到一个 access/refresh 令牌对。访问令牌在 20 分钟后过期,而刷新令牌的有效期为 180 天。

现在,当客户端由于访问令牌过期而收到 HTTP 401 未授权时,它将使用刷新令牌来获取新的 access/refresh 令牌对。同时,我们使后端数据库中的旧令牌对无效(我们只是删除条目)。

这有一些主要问题,因为我们的客户端是移动应用程序,有时可能会发生客户端未收到来自我们服务器的响应。因此,在我们的后端保存了新的令牌对之后,由于网络问题等原因,客户端没有收到新的令牌对,客户端无法再获得新的令牌对,因为他仍然只知道旧的——现在无效的——刷新令牌。

我想知道我们正在做的事情是否正确,或者我们是否真的不应该从数据库中删除旧的刷新令牌,只要它们没有过期。或者我们是否应该记住用户的最后 1 或 2 个刷新令牌,这样即使创建了一个新令牌,如果客户端没有收到我们服务器的响应,他仍然可以用旧的再次尝试一两次刷新令牌。

或者我们是否应该在获取新的访问令牌时永远不发送新的刷新令牌并始终使用相同的刷新令牌?

是否有任何最佳实践可供遵循,或者这完全是个人喜好?我的意思是我们不能第一个 运行 解决这个移动客户端因网络问题而失去响应的问题,对吧? :)

测量移动连接发生次数

当出现移动连接问题时,我预计刷新令牌授予 request 会失败。对于请求成功和 response 未能到达客户端(在这么短的时间内 window,例如 200 毫秒)感觉非常像边缘情况。

我的目标是确保围绕服务器端发生的事情进行良好的生产日志记录,以便您可以更清楚地了解确切原因。否则很容易得出错误的结论。

轮换刷新令牌

从安全角度来看,首选行为是在旧令牌被重新使用时撤销用户的所有令牌。但是,OIDC Specs 表明这可能会在某些设置中导致可用性问题,在这种情况下 other measures 可能是合适的。

确切的行为是特定于提供商的 - 一些授权服务器存储和标记旧的刷新令牌,并可能允许它们 reused for a time period 针对客户端应用程序进行配置。

安全与可用性

如果处理高价值数据,我会使用更安全的选项,但如果移动消费数据不是特别敏感,使用 non-rotating 刷新令牌可能是一个合适的措施。

可靠的应用程序

在某些情况下,OAuth 客户端在使用刷新令牌时会收到 401,除了您提到的情况外,还有其他可能的原因:

  • 令牌签名或 cookie 加密密钥更新(在某些设置中)
  • 基础架构更改,例如负载平衡故障转移到备用站点(在某些设置中)

应始终对应用程序进行可靠编码以处理此问题,例如:

  • 当 API 调用失败并显示 401 时,尝试刷新访问令牌
  • 当令牌刷新失败时,例如 error 响应字段中出现 401 或 invalid_grant 值,用户必须 re-authenticate

请注意,re-authentication 有时是单点登录事件。要查看它的外观,您可以 运行 我的 Demo Single Page App 并单击 Expire Refresh Token,然后单击 Reload Data

摘要

在分布式系统世界中,您不能总是保证 180 天没有 re-logins。就后续步骤而言,我的偏好是正确识别失败的原因和频率,并查看是否可以提高客户端应用程序代码的可靠性。

我正在努力将 oauth 2 添加到我们正在构建的 API,所以我还没有 运行 进入这个特定问题,但我知道它可能成为一个问题我们。我读过一种解决方法,您可以将其过期时间调整为比当前日期早几分钟,而不是简单地 revoking/deleting 使用过的刷新令牌。基本上是一个小的宽限期。这让客户端有机会 re-use 如果他们未能收到来自先前请求的更新令牌的响应。

这方面的一个例子是 Fitbit,他们实际上通过为撤销的令牌提供 2 分钟的宽限期来做类似的事情

https://community.fitbit.com/t5/Web-API-Development/Refresh-token-amp-network-timeout/td-p/1102761

我不确定它今天是否仍然适用,因为上面的 post 是 6 年前的。