处理JWT过期和智威汤逊负载更新

问题描述:

我有一个基于Koa的Node.js后端,用于我的个人/业余爱好应用程序。处理JWT过期和智威汤逊负载更新

我用JWT令牌实现了会话处理。客户端(AngularJS)在成功登录后获取令牌并将令牌存储在某处(目前在sessionStorage中,但对于此问题而言,这应该不重要)。

我有两个问题:

  1. 当我需要更新其JWT表示,比方说,用户打开2FA于是我问他提供他的电话号码,我想用户记录在用户记录中设置此电话号码。目前,在成功验证电话号码后,我打电话给后台更新用户记录,并使用更新后的用户记录创建了新的JWT令牌(我从JWT令牌中排除了敏感信息,例如哈希密码,但我想包括客户端使用的电话号码)。当某些凭证更改并使用此新令牌更新现有客户端令牌时,是否可以创建新令牌?我是否永远不会创建另一个令牌,只有在成功验证后才创建一个令牌?我如何更新令牌中的有效载荷?

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

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

    2.2。 JWT设置时间长,例如1周,如果到期,我会选择从客户端重新进行身份验证。

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

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

+0

为什么不只是使用cookie? – Kebman

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

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

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

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

现在回答你第一个问题,如果你要根据你更新的用户记录,以更新您的智威汤逊的有效载荷,然后就可以使用相同的刷新令牌来产生与更新的有效载荷新的访问令牌。逻辑保持不变,因为如果用户记录中存在电话号码,它将被添加到有效内容中,否则它将在有效内容中为空。

使用刷新标记的主要优点是访问令牌可以在任何时间使用刷新令牌

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

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

(重点是我的;源refresh tokens

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

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

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

该签名用于验证JWT的发件人是谁说它是并确保邮件未被更改。

(重点是我的;源JSON web tokens

说了这么多,我会考虑以下几点:

  1. 问问自己,如果你真的需要JWT的或者定期的会话标识符存储为饼干(HTTP Only)将简化您的逻辑。
  2. 例如,如果需要JWT,则您有另一个API也会接受这些令牌作为认证,那么我会考虑选项2.1或2.2作为不建议基于浏览器的应用程序的刷新令牌。

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

的另一点是,在你的应用程序将公开访问令牌攻击者作为注入脚本像XSS漏洞将能够从localStorage/sessionStorage阅读,这样可以有利于HTTP唯一的会话cookie存储的另一点。