问题 在JWT中更新/更改角色声明(或任何其他声明)


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

如果角色发生了变化。我怎么能在所有代币中反映这一点?我考虑过几个解决方案:

  • 如果我使用刷新令牌,则用户必须等到访问令牌的到期日期到期。

  • 我可以记录已更改的用户ID并检查每个请求,然后在用户更改后返回新令牌。

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


10939
2018-05-15 11:13


起源

你用什么来生成JWT? IdentityServer? Openddict? - kg743
要么:设置短令牌生命周期。在身份发生变化时请求用户reauths。使用参考标记。这里有关于ref令牌的简要概述 leastprivilege.com/2015/11/25/... 想要在Active Directory中更改用户组时需要重新登录,这是一个很好的心理跳跃。如果用户没有,他们仍然拥有相同的旧组。如果它足够好,它对你来说应该足够好了。除非你想要一个真正的用户不友好的解决方案,他们必须每5秒钟一次。 ;) - Mardoxx
@KevinGysberg我使用来自System.Identity.Tokens的JwtSecurityTokenHandler。但生成令牌不是问题:) - tobbe


答案:


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

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

我不相信有一个适当的标准,因为jwt是设计不可变的,如果你需要“更新”它,你必须完全改变它。


6
2018-05-18 15:13



嗯好,这很聪明,但我确实失去了无国籍(一句话?),这应该是JWT的力量之一。也许我应该随机使用令牌..? :) - tobbe
不确定我是否正确使用了这个,但是JWT对于安全的信息交换也很有用,这意味着您可以将数据放入其中,可以用于验证和潜在的重新生成。 - Aperçu
哦,我想我明白了,我们不是在谈论服务器或数据库中的会话,而是数据库中已经存在的关于用户角色的信息,而不是处理JWT的额外实现,不要我相信这是一回事。 - Aperçu
您是否会根据站点范围的版本号(可能存储在配置文件中)或存储在数据库中的特定用户的版本号来检查存储在jwt中的版本?因为如果它不是站点范围的那么你必须在每个请求上点击数据库吗? - spencer.sm


JWT令牌是不可变的,因此您无法更改/更新现有令牌的声明 - 因此您必须发出新的JWT令牌。

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

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

  • 使用黑名单来保存已撤销的令牌列表(当然这样会丢失'无状态'部分)

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

最好的解决方案取决于具体情况。


4
2018-05-17 15:17





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


0
2017-08-18 19:34