处理JWT到期和JWT有效负载更新

我有一个基于Koa的Node.js后端,用于我的个人/业余爱好应用程序。

我用JWT令牌实现了会话处理。 客户端(AngularJS)在成功login后获取令牌并将令牌存储在某个地方(目前在sessionStorage但对于这个问题目的不重要)。

我有两个问题:

  1. 当我需要更新JWT代表的用户logging时,比方说,用户打开了2FA,所以我要求他提供他的电话号码,我想在用户的logging中设置这个电话号码。 目前,在电话号码成功validation后,我打电话给我的后端更新用户logging,我创build一个新的JWT令牌与更新的用户logging(我排除敏感信息从JWT令牌像散列密码,但我想包括客户端使用的电话号码)。 当某些凭证更改并使用此新令牌更新现有客户端令牌时,是否可以创build新令牌? 我是否永远不会创build另一个令牌,只有在成功validation后才创build一个令牌? 我如何更新令牌中的有效载荷?

  2. 我应该如何处理过期的JWT令牌? 在我看来,我有3(可能)的情况:

    2.1。 智威汤逊(JWT)设置为短暂的生活,比如15分钟。 如果后端服务器回复401 Unauthenticated“Invalid token”(我猜这是koa-jwt的默认行为),那么我会自动注销我的客户端,并要求重新validation。 但是我也build立了一个互补的中间件,这个中间件是后端链中的最后一个,用刷新的到期来重新创build令牌,并且客户端也用已刷新的令牌代替现有的令牌。 因此,如果用户处于活动状态,并且每个受保护的API调用都使用该应用程序,则在成功的情况下,将创build一个新的令牌来replace旧的令牌。

    2.2。 JWT的设置时间很长,比如说1周,如果到期,我会从客户那里select重新authentication。

    2.3。 复制https://tools.ietf.org/html/rfc6749#section-1.5 。 在成功validation后创buildJWT令牌时,我们发送一个access_token以及一个refresh_token。 当access_token过期并且服务器响应HTTP 401'无效标记'( koa-jwt默认值)时,客户端将refresh_token发送给支持者以要求新的access_token(以及可选的新的refresh_token)。 在这种情况下,我不完全了解refresh_token如何validation旧的access_token以提供新的令牌? 或者为什么我们需要有一个refresh_token?

关于上层主题(JWT更新和JWT到期)的任何通用build议将会有所帮助。

我想在回答第一个问题之前回答第二个问题。

基本上你提到的第三个选项是更新你的访问令牌的最好方法。 访问令牌应该是短暂的(~5分钟),刷新令牌寿命更长。 当您的访问令牌过期时,将刷新令牌发送到后端并获取新的访问令牌。 所以你的回应应该是这样的:

 { "token_type":"bearer", "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s", "expires_in":10, "refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b" } 

所以想法是把你的应用程序分成授权服务器(它产生访问令牌/刷新令牌)和资源服务器(validation访问令牌并访问资源)。 您可以维护一个模式,以根据授权服务器中的访问令牌validation刷新令牌。 请参考这个链接中提到的模式部分,这可能会给你一些想法。 Oauth2 。 您可以根据需要修改架构。 对于每个请求调用,您不需要将刷新令牌与访问令牌一起发送。 刷新令牌只能发送给授权服务器来生成新的访问令牌。 如何生成刷新令牌? 如果我使用Java,我将使用UUID.randomUUID()来生成一个唯一的刷新标记。

现在回答你的第一个问题,如果你想根据你更新的用户logging更新你的JWT有效载荷,那么你可以使用相同的刷新标记来生成一个新的有效载荷的访问令牌。 逻辑保持不变,因为如果用户logging中存在电话号码,则将其添加到有效内容中,否则将在有效内容中为空。

使用Refresh令牌的主要优点是可以随时使用刷新令牌来更新访问令牌

从底部开始,我会忽略刷新令牌,因为我认为他们不会帮助你。 它们通常针对客户端应用程序可以提供比用户浏览器更安全的存储的其他scheme – 考虑原生移动应用程序或服务器端Web应用程序。

刷新令牌是长寿的 。 这意味着,当一个客户端从服务器获取一个,这个令牌必须被安全地存储,以防止被潜在的攻击者使用, 因此,将它们存储在浏览器中是不安全的。

(重点是我的;源刷新令牌 )

这意味着选项2.3基本上与2.2相同,这不是一个坏的select。 具有长会话持续时间的Web应用程序并不罕见。 如果您的应用程序不是非常敏感,则可以使用长时间会话来改善用户体验。 例如,Django会话cookie的使用时间默认为两周。 请参阅SESSION_COOKIE_AGE 。

剩下的选项(2.1)通常被称为滑动会话。 会话超时很短,但只要用户在该时间间隔内继续使用应用程序,会话就会自动更新。 这可能是最常用的方法,或者至less是我最常用的方法,所以我是有偏见的。 我唯一要注意的是,滑动会话通常是以不透明的会话标识符实现的,这些会话标识符存储在客户端作为cookie,然后存储在服务器上。

您的方法有点不同,因为您有一个存储在浏览器本地存储上的无状态JWT令牌(它包含实际的用户数据)。 就像你说的,为了更新令牌,你必须生成一个新的令牌,因为你必须生成一个新的签名。

签名用于validationJWT的发件人是谁说的, 并确保邮件没有被改变。

(重点是我的;源JSONnetworking令牌 )

说完这一切,我会考虑以下几点:

  1. 问问自己是否真的需要JWT,或者如果将常规会话标识符存储为Cookie( 仅限HTTP )将简化您的逻辑。
  2. 如果JWT是必需的,例如,你有另一个API也可以接受这些令牌作为authentication,那么我会考虑选项2.1或2.2作为基于浏览器的应用程序的刷新令牌。

话虽如此,你还应该考虑到智威汤逊不是很大,但是如果你决定自动更新的话,他们仍然是一个开销。 您可以通过select20分钟的会话持续时间来缓解这一点,并且仅在会话过去一半之后才执行自动续订。

还有一点是,应用程序中的XSS等漏洞会将访问令牌暴露给攻击者,因为注入的脚本可以从localStorage / sessionStorage读取,这可能是另一个有利于仅HTTP会话cookie存储的点。