Authentication 更新/更改JWT中的角色声明(或任何其他声明)

Authentication 更新/更改JWT中的角色声明(或任何其他声明),authentication,oauth,asp.net-core,jwt,asp.net-core-webapi,Authentication,Oauth,Asp.net Core,Jwt,Asp.net Core Webapi,我将用户角色存储在JWT中(以限制API端点)。管理员可以更改角色 如果角色发生变化。我应该如何在所有代币中反映这一点?我考虑了几个解决方案: 如果我使用刷新令牌,用户将不得不等到访问令牌的过期日期 我可以记录更改的用户ID并检查每个请求,如果用户已更改,则返回一个新令牌 有没有标准的方法可以做到这一点?JWT令牌是不可变的,因此您不能更改/更新现有令牌上的声明-因此您必须发布新的JWT令牌 这导致了JWT令牌撤销的最大问题。没有好的解决办法。你能做的就是 缩短JWT到期日期(并且可以选择

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

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

  • 如果我使用刷新令牌,用户将不得不等到访问令牌的过期日期

  • 我可以记录更改的用户ID并检查每个请求,如果用户已更改,则返回一个新令牌


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

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

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

  • 缩短JWT到期日期(并且可以选择使用刷新令牌)

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

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


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

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

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


我不认为有合适的标准,因为jwt在设计上是不可变的,如果需要“更新”它,您必须完全更改它。

要解决这个问题,您可以缩短令牌的生存期,一旦令牌过期,您可以在隐式授权的情况下以静默方式续订令牌,或者使用刷新令牌机制从授权服务器发出新令牌。一旦角色发生更改,它可能不会立即反映在令牌中,但一旦令牌续订,它将可用

@Janar说有三种解决方案可以处理不同的场景,但它们仍然存在相应的缺点

我还想撤销您的代币:

  • iat
    设置为JWT有效载荷。(您应该知道什么是
    iat
  • 撤销用户的令牌:
    • 查找用户id
    • 让身份验证服务器拒绝在当前时间之前(由iat判断)且属于此用户(由用户ID判断)的令牌

  • 您使用什么来生成JWT?身份服务器?Openddict?任意:设置较短的令牌生存期。当用户的身份更改时请求用户重新授权。使用引用标记。这里有一个关于ref令牌的简要概述,当您在Active Directory中更改用户组时,它需要重新登录,这是一个很好的心理障碍。如果用户没有,则它们仍然具有相同的、旧的组。如果足够好的话,对你来说也应该足够好。除非你想要一个真正对用户不友好的解决方案,他们必须每5秒重新授权一次@KevinGysberg Im使用System.Identity.Tokens中的JwtSecurityTokenHandler。但是生成令牌不是问题:)嗯,好吧,这很聪明,但我确实失去了无状态性(一个词?),这应该是JWTs的优势之一。也许我应该带上一个随机标记……?:)我不确定我是否正确,哈哈,但是JWT对于安全的信息交换也很有用,这意味着你可以将数据放入其中,用于验证和潜在的重新生成。哦,我想我明白了,我们不是在讨论服务器或数据库中的会话,相反,它是数据库中已经存在的关于用户角色的信息,而不是处理JWTs的附加实现,不要相信这是同一回事。您会根据站点范围的版本号(可能存储在配置文件中)检查存储在jwt中的版本吗或者数据库中存储的特定用户的版本号?因为如果它不是站点范围的,那么您必须在每个请求上访问数据库,对吗?