JWT(JSON Web Token)自动延长到期时间

 手机用户2502903715 发布于 2022-12-13 10:36

我想对我们的新REST API实现基于JWT的身份验证.但是由于在令牌中设置了到期,是否可以自动延长它?如果他们在那段时间内积极使用该应用程序,我不希望用户在每X分钟后需要登录.这将是一个巨大的用户体验失败.

但是延长过期会创建一个新令牌(旧令牌在到期之前仍然有效).每次请求后生成一个新令牌听起来很愚蠢.当多个令牌同时有效时,听起来像是一个安全问题.当然,我可以使用黑名单使旧的旧的无效,但我需要存储令牌.JWT的一个好处就是没有存储空间.

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

但同样,要实现这一点(没有Auth0),我需要存储刷新令牌并保持其过期.那么真正的好处是什么?为什么不只有一个令牌(不是JWT)并在服务器上保持过期?

还有其他选择吗?使用JWT不适合这种情况吗?

7 个回答
  • 在您自己处理auth的情况下(即不使用Auth0之类的提供程序),以下内容可能有效:

      发出JWT令牌,到期时间相对较短,比如15分钟.

      应用程序在任何需要令牌的交易(令牌包含到期日期)之前检查令牌到期日期.如果令牌已过期,则它首先要求API"刷新"令牌(这对UX是透明的).

      API获取令牌刷新请求,但首先检查用户数据库以查看是否已针对该用户配置文件设置了"reauth"标志(令牌可以包含用户ID).如果该标志存在,则拒绝令牌刷新,否则发出新令牌.

      重复.

    例如,当用户重置密码时,将设置数据库后端中的"reauth"标志.用户下次登录时会删除该标志.

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

    2022-12-13 10:37 回答
  • 我实际上是在PHP中使用Guzzle客户端为api创建了一个客户端库,但这个概念应该适用于其他平台.

    基本上,我发行了两个令牌,一个短的(5分钟)和一个长的,在一周后到期.如果客户端库收到对某个请求的401响应,则使用中间件尝试刷新短令牌.然后它将再次尝试原始请求,如果能够刷新,则对用户透明地获得正确的响应.如果失败,它只会将401发送给用户.

    如果短令牌已过期,但仍然是可信的并且长令牌有效且可信,则它将使用长令牌进行身份验证的服务上的特殊端点刷新短令牌(这是唯一可以使用的).然后它将使用短令牌获取新的长令牌,从而每次刷新短令牌时将其延长一周.

    这种方法还允许我们在最多5分钟内撤销访问权限,这对于我们的使用是可以接受的,而不必存储令牌的黑名单.

    延迟编辑:重新阅读这几个月后,我应该指出你可以在刷新短令牌时撤销访问权限,因为它提供了更昂贵的调用的机会(例如,调用数据库以查看用户是否已被禁止),无需在每次拨打您的服务时付费.

    2022-12-13 10:37 回答
  • 在后端使用RESTful apis将应用程序移动到HTML5时,我正在修补.我想出的解决方案是:

      成功登录后,将向客户端发出一个会话时间为30分钟(或通常的服务器端会话时间)的令牌.

      创建客户端计时器以调用服务以在令牌到期之前续订令牌.新令牌将替换将来调用中的现有令牌.

    如您所见,这减少了频繁的刷新令牌请求.如果用户在触发续订令牌呼叫之前关闭浏览器/应用程序,则先前令牌将及时到期,用户必须重新登录.

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

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

    2022-12-13 10:37 回答
  • 好问题 - 问题本身就有丰富的信息.

    文章Refresh Tokens:何时使用它们以及它们如何与JWT交互为这种情况提供了一个好主意.一些要点是: -

    刷新令牌包含获取新访问令牌所需的信息.

    刷新令牌也可以过期但是相当长寿.

    刷新令牌通常受到严格的存储要求,以确保它们不会泄露.

    它们也可以被授权服务器列入黑名单.

    另请参阅auth0/angular-jwt angularjs

    对于Web API.read 使用ASP .NET Web API 2和Owin在AngularJS App中启用OAuth刷新令牌

    2022-12-13 10:37 回答
  • 在后端没有任何额外安全存储的情况下,使JWT无效的替代解决方案是jwt_version在users表上实现新的整数列.如果用户希望注销或使现有令牌过期,则只需增加该jwt_version字段.

    生成新的JWT时,将其编码jwt_version到JWT有效负载中,如果新的JWT应该替换所有其他JWT,则可以选择性地增加该值.

    在验证JWT时,将该jwt_version字段user_id与其进行比较,并且只有在匹配时才授予授权.

    2022-12-13 10:38 回答
  • 智威汤逊 - 自动刷新

    如果您使用的是节点(React/Redux/Universal JS),则可以安装npm i -S jwt-autorefresh.

    此库根据用户计算的访问令牌到期之前的秒数(基于令牌中编码的exp声明)计划刷新JWT令牌.它有一个广泛的测试套件,可以检查很多条件,以确保任何奇怪的活动都伴随着有关环境配置错误的描述性消息.

    完整的示例实现

    import autorefresh from 'jwt-autorefresh'
    
    /** Events in your app that are triggered when your user becomes authorized or deauthorized. */
    import { onAuthorize, onDeauthorize } from './events'
    
    /** Your refresh token mechanism, returning a promise that resolves to the new access tokenFunction (library does not care about your method of persisting tokens) */
    const refresh = () => {
      const init =  { method: 'POST'
                    , headers: { 'Content-Type': `application/x-www-form-urlencoded` }
                    , body: `refresh_token=${localStorage.refresh_token}&grant_type=refresh_token`
                    }
      return fetch('/oauth/token', init)
        .then(res => res.json())
        .then(({ token_type, access_token, expires_in, refresh_token }) => {
          localStorage.access_token = access_token
          localStorage.refresh_token = refresh_token
          return access_token
        })
    }
    
    /** You supply a leadSeconds number or function that generates a number of seconds that the refresh should occur prior to the access token expiring */
    const leadSeconds = () => {
      /** Generate random additional seconds (up to 30 in this case) to append to the lead time to ensure multiple clients dont schedule simultaneous refresh */
      const jitter = Math.floor(Math.random() * 30)
    
      /** Schedule autorefresh to occur 60 to 90 seconds prior to token expiration */
      return 60 + jitter
    }
    
    let start = autorefresh({ refresh, leadSeconds })
    let cancel = () => {}
    onAuthorize(access_token => {
      cancel()
      cancel = start(access_token)
    })
    
    onDeauthorize(() => cancel())
    

    免责声明:我是维护者

    2022-12-13 10:38 回答
  • 我在Auth0工作,我参与了刷新令牌功能的设计.

    这一切都取决于应用程序的类型,这是我们推荐的方法.

    Web应用程序

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

    将令牌过期设置为一周,并在每次用户打开Web应用程序时每隔一小时刷新令牌.如果用户未打开应用程序超过一周,则必须再次登录,这是可接受的Web应用程序UX.

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

    移动/本机应用程序

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

    我们的想法是刷新令牌永不过期,并且可以始终为有效的JWT进行交换.

    永不过期的令牌问题绝不是永远不会.如果丢失手机怎么办?因此,它需要以某种方式由用户识别,并且应用程序需要提供撤销访问的方法.我们决定使用该设备的名称,例如"maryo的iPad".然后,用户可以转到该应用程序并撤消对"maryo的iPad"的访问权限.

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

    我们认为JWT对这些用例没用,所以我们使用随机生成的字符串,然后将它存储在我们这边.

    2022-12-13 10:38 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有