提问者:小点点

JWT(JSON Web令牌)过期自动延长


我想对我们的新REST API实现基于JWT的身份验证。但既然在令牌中设置了到期时间,有没有可能自动延长呢?我不希望用户需要在每X分钟后登录,如果他们在那个时期正在积极使用应用程序。那将是一个巨大的UX失败。

但是延长到期时间会创建一个新的令牌(而旧的令牌在到期之前仍然有效)。在每个请求之后生成一个新令牌对我来说听起来很傻。当多个令牌同时有效时,听起来像是一个安全问题。当然,我可以使用黑名单使旧的旧的失效,但我需要存储代币。JWT的一个好处是没有存储。

我找到了Auth0是如何解决它的。它们不仅使用JWT令牌,还使用刷新令牌:https://docs.auth0.com/refresh-token

但是,要实现这一点(没有Auth0),我需要存储刷新令牌并维护它们的到期时间。那么真正的好处是什么呢?为什么不只有一个令牌(不是JWT),并在服务器上保留到期时间呢?

还有别的选择吗?使用JWT不适合这个场景吗?


共3个答案

匿名用户

我在Auth0工作,我参与了刷新令牌特性的设计。

这完全取决于应用程序的类型,下面是我们推荐的方法。

一个好的模式是在令牌过期之前刷新它。

将令牌过期时间设置为一周,并在用户每次打开web应用程序时和每隔一小时刷新令牌。如果用户超过一周没有打开应用程序,他们将不得不再次登录,这是可以接受的web应用程序UX。

要刷新令牌,您的API需要一个新的端点,该端点接收有效的,未过期的JWT,并返回具有新过期字段的相同签名的JWT。然后web应用程序将把令牌存储在某个地方。

大多数本机应用程序只登录一次。

其思想是刷新令牌永远不会过期,并且可以始终将其交换为有效的JWT。

永不过期的令牌的问题在于,永不意味着永不。如果你丢了手机怎么办?因此,它需要以某种方式被用户识别,并且应用程序需要提供一种撤销访问的方法。我们决定使用设备的名字,例如“Maryo's iPad”。然后用户就可以转到应用程序并撤销对“Maryo's iPad”的访问权限。

另一种方法是撤销特定事件上的刷新令牌。一个有趣的事件是更改密码。

我们认为JWT对这些用例没有用处,所以我们使用一个随机生成的字符串,我们把它存储在我们这边。

匿名用户

在您自己处理身份验证的情况下(即不使用像Auth0这样的提供程序),以下操作可能会起作用:

  1. 发行有效期较短的JWT令牌,例如15分钟。
  2. 应用程序在任何需要令牌的事务之前检查令牌到期日期(令牌包含到期日期)。如果令牌已过期,则它首先要求API“刷新”令牌(这对UX是透明的)。
  3. API获取令牌刷新请求,但首先检查用户数据库,查看是否针对该用户配置文件设置了“reauth”标志(令牌可以包含用户id)。如果该标志存在,则拒绝令牌刷新,否则将发出新令牌。
  4. 重复。

例如,当用户重置密码时,数据库后端中的“reauth”标志将被设置。当用户下次登录时,该标志将被移除。

此外,假设您有一个策略,用户必须至少每72小时登录一次。在这种情况下,API令牌刷新逻辑还将从用户数据库中检查用户的上次登录日期,并在此基础上拒绝/允许令牌刷新。

匿名用户

在将我们的应用程序移动到HTML5时,我在后端使用了RESTful API。我想出的解决办法是:

  1. 成功登录时,向客户端颁发会话时间为30分钟(或任何通常的服务器端会话时间)的令牌。
  2. 创建一个客户端计时器来调用服务,以便在令牌到期之前续订令牌。新令牌将在以后的调用中替换现有令牌。

如您所见,这减少了频繁的刷新令牌请求。如果用户在触发更新令牌调用之前关闭浏览器/应用程序,则上一个令牌将及时过期,用户将不得不重新登录。

可以实现更复杂的策略来满足用户不活动的情况(例如忽略了打开的浏览器选项卡)。在这种情况下,renew令牌调用应该包括预期的过期时间,该过期时间不应该超过定义的会话时间。应用程序必须相应地跟踪上次用户交互。

我不喜欢设置长过期的想法,因此这种方法可能不适用于需要较少频繁身份验证的本机应用程序。