首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理JWT过期和JWT有效载荷更新

处理JWT过期和JWT有效载荷更新
EN

Stack Overflow用户
提问于 2016-10-03 06:52:59
回答 2查看 11.3K关注 0票数 10

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

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

我有两个问题:

  1. 当我需要更新JWT所代表的用户记录时,比如说,用户打开了双因素身份验证(2FA),所以我要求他提供他的电话号码,我想在用户的记录中设置这个电话号码。目前,在成功验证电话号码之后,我调用后端更新用户记录,并使用更新的用户记录创建一个新的JWT令牌(我将敏感信息排除在JWT令牌中,比如散列密码,但我希望包括用于客户端使用的电话号码)。当一些凭据更改并用这个新令牌更新现有的客户端令牌时,创建一个新令牌可以吗?我应该永远不会创建另一个令牌,只创建一个,并且只在成功的身份验证时创建?然后如何更新令牌中的有效负载?
  2. 我应该如何处理过期的JWT令牌?在我看来,我有三种(可能的)情况:

2.1。JWT是短命的,比如说15分钟。如果后端服务器使用401个未经身份验证的“无效令牌”(我猜这是koa-jwt的默认行为)进行应答,那么我会自动注销我的客户机并要求重新验证。但是,我还设置了一个补充中间件,它是后端链中的最后一个中间件,用于重新创建更新到期的令牌,客户端也将用刷新的令牌替换现有的令牌。因此,如果用户是活动的,并且使用应用程序,那么如果成功,每个受保护的API调用都会创建一个新的令牌来替换旧的令牌。

2.2。JWT被设置为长寿,比如1周,如果它到期,我将从客户端选择重新身份验证。

2.3。复制https://www.rfc-editor.org/rfc/rfc6749#section-1.5。在这里,在成功身份验证之后创建JWT令牌时,我们发送一个access_token和一个refresh_token。当access_token过期,服务器使用HTTP401“无效令牌”(koa-jwt默认值)进行响应时,客户端将refresh_token发送到后端,以要求一个新的access_token (可选为新的refresh_token)。在这种情况下,我不完全理解refresh_token是如何根据旧的access_token进行验证以提供新令牌的?或者为什么我们需要一个refresh_token?

任何关于高级主题(JWT更新和JWT过期)的一般性建议都是有帮助的。

EN

回答 2

Stack Overflow用户

发布于 2016-10-03 09:29:09

从底部开始,我将忽略刷新令牌,因为我认为它们不会在这里帮助您。它们通常针对其他情况,客户端应用程序可以提供比用户浏览器更安全的存储--比如本地移动应用程序或服务器端web应用程序。

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

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

这意味着选项2.3基本上与2.2相同,这是一个不错的选择。使用长会话时间的web应用程序并不少见。如果您的应用程序不是很敏感,那么使用长会话来改善用户体验是可以接受的。例如,Django使用默认的两周作为会话cookie的使用时间。见年龄

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

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

该签名用于验证JWT的发送方是否是它所称的,并确保消息不会以这种方式更改。

(重点是我的;源JSON网络令牌)

话虽如此,我仍会考虑以下几点:

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

尽管如此,您还应该考虑到JWT不是很大,但是如果您决定自动更新,它们仍然是一种开销。您可以通过选择20分钟的会话持续时间来稍微减轻这种情况,并且只在一半的会话结束后执行自动更新。

另一点是,应用程序中的XSS这样的漏洞将向攻击者公开访问令牌,因为注入的脚本将能够从localStorage/sessionStorage中读取,这可能是另一个有利于HTTP存储的漏洞。

票数 6
EN

Stack Overflow用户

发布于 2016-10-03 09:25:40

在我开始第一个问题之前,我想回答你的第二个问题。

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

代码语言:javascript
复制
{
"token_type":"bearer",
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
"expires_in":10,
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b"
}

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

现在要回答第一个问题,如果您想要根据更新的用户记录更新JWT有效负载,那么您可以使用相同的刷新令牌来生成一个具有更新的有效负载的新访问令牌。逻辑保持不变,因为如果用户记录中存在电话号码,它将被添加到有效负载中,如果没有,则在有效负载中为空。

使用Refresh令牌的主要优点是可以在任何时候使用Refresh令牌更新访问令牌。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39825953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档