Update/change JWT 中的角色声明(或任何其他声明)

Update/change roles claim (or any other claim) in JWT

我将用户角色存储在 JWT 中(以限制 API 端点)。管理员可以更改角色。

如果角色发生变化。我应该如何在所有令牌中反映这一点?我考虑了几个解决方案:

有没有标准的方法来做到这一点?

JWT 令牌是不可变的,因此您不能 change/update 声明现有令牌 - 因此您必须发布新的 JWT 令牌。

这导致了 JWT 的最大问题——令牌撤销。没有好的解决办法。你能做的是

  • 保持 JWT 到期日期较短(并可选择使用刷新令牌)

  • 使用黑名单保留已撤销令牌的列表(当然这样会丢失 'stateless' 部分)

  • 更改密钥(请记住,这会撤销所有用户的所有有效令牌)

最佳方案视具体情况而定。

如果您关心即时更改,刷新令牌似乎不是解决方案,如果您撤销用户的权限,您可能不希望用户在一段时间内访问审核工具。

您可以做的是在 jwt 令牌中保留一个相对于用户的版本号,就像 mongoose 使用 versionKey 的方式一样。通过这样做,您将能够根据给定用户的数据库中的版本检查此版本。每次更改此用户的角色时,都会增加此版本,如果 jwt 的版本不匹配,只需重新创建一个具有正确角色和版本的新版本并将其发回给用户。

我认为对此没有合适的标准,因为 jwt 在设计上是不可变的,如果需要 "update",则必须完全更改它。

为了解决这种情况,您可以缩短令牌的生命周期,一旦令牌过期,您可以在隐式授予的情况下静默更新令牌,或者使用刷新令牌机制从授权服务器颁发新令牌。一旦角色发生变化,它可能不会立即反映在令牌中,但一旦更新令牌,它就会可用。

@Janar说了三种解决方案来应对不同的场景,但都存在相应的弊端。

我也想撤销你的令牌:

  1. iat 设置为 JWT 负载。 (你应该知道什么是iat
  2. 撤销用户的令牌:
    • 找到用户id
    • 让auth服务器拒绝当前时间之前(通过iat判断)属于该用户(通过userId判断)的token

对此的解决方案是在使用 JWT 令牌时将身份验证和授权分开。使用令牌进行身份验证(申请 ID)并使用该 ID 检查数据库中的授权。考虑到您现在必须检查每个请求的授权,这会增加每个请求的延迟。然而,这可以通过使用内存中的数据结构存储(例如 Redis)作为缓存来缓解。在每次权限更改时,删除缓存并再次调用权限。