如何以及为什么使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗?

How and why handle jwt token expiration with refresh_token, is there another alternative?

我有两场战争:app.war(struts web app) 和 rest.war(classic rest api)。

app.war 通过用户登录 app.war 成功后生成的 jwt 令牌访问 rest.war

当用户使用 a.war 时,需要通过使用 jwt 令牌从 a.war 的 jsp 发送 ajax 调用来从 rest.war 获取一些数据。

jwt 令牌的过期时间是 15 分钟,而 app.war 的会话超时是 1 小时。

但是,如果 jwt 令牌已过期,甚至会弹出要求用户重新登录,用户仍然可以访问 app.war

还有一种选择:使用access_tokenrefresh_token,如果access_token过期,则使用refresh_token获取新的access_tokenrefresh_token.

对于这种方法,我有一些疑问:

首先,为什么要用两个token?因为我认为它们是相同的,只是 refresh_tokenaccess_token 活得更长,并使用 refresh_token 获得新的 access_token,所以为什么不直接 access_token 并设置它过期时间更长?

其次,生成access_tokenrefresh_token的算法是一样的吗,只是过期时间不一样?

第三,如果客户端使用令牌执行多个 api 调用(同步和异步),如果其中一个调用 return 401 如何处理(令牌已过期)?

正如您所说,refresh_token 是处理 jwt 过期的推荐替代方案。

为什么要使用两个令牌?

因为使用两个令牌(access_token 和 refresh_token)是世界 class 公司(google、azure、亚马逊等)使用的经过验证的策略信任 OAuth 2.0 授权框架

它是 Internet 工程任务组 (IETF) 的产品,而 IETF 又是: Internet 工程任务组 (IETF) 是一个开放标准组织,它开发和推广自愿性 Internet 标准,尤其是那些包括互联网协议族。

您可以使用严格遵守其 specification 的 oauth2 框架,创建和混合关注您的自定义需求或开发具有新概念的新框架

那么为什么不直接 access_token 并将其过期时间设置得更长一些呢?

Oauth2 规范不推荐 non-expirable 令牌。 token word 本身就是一个可以过期的东西。如果它没有过期,我们可以使用密码。

例如,让我们想象一个需要令牌才能下载一些用户信息的移动应用程序。如果令牌没有过期,小偷就可以窃取移动应用程序,进入并访问用户信息。但由于令牌意味着过期,小偷可能有时间限制的访问。此外,用户在窃取时可能会 revoked 令牌,因此小偷无法访问。

通常当令牌过期时,会强制登录。但是有一些要求用户不想每 3600 毫秒登录一次。因此 refresh_token 有助于不打扰我们的用户,并且 无需人工登录即可获得新的 access_token。现在,如果 refresh_token 没有过期会怎样?我们可以从几个月或几年创建 access-tokens 吗?这就是为什么 refresh_token 也必须过期

生成access_token和refresh_token的算法是一样的吗,只是过期时间不一样?

我实现了一种安全服务器,我使用了相同的算法但到期时间不同。但是我添加了一个额外的声明来区分它们:

  • How to differentiate refresh_token from access_token at validation stage in security server?

多次调用需要 access_token

在这种情况下,如果在每次用户登录时更新令牌,您将有一个 access_token 可以使用 3600 毫秒的生命周期。

在那之后你的用户有点像机器人(或者是你的网络的 feature/requirement)并开始使用多种形式对你的其余部分执行多次调用 api 附加 access_token.

如果我们在 3601 毫秒内,在下一个来自 Web 的 api 调用中,api 必须 return 一个 403 错误并显示一个 classic 弹出窗口: 会话已过期,请点击此处重新登录...

如果您的要求是避免出现此弹出窗口,您可以选择以下方法之一:

  • 在出现 403 错误时使用刷新令牌更新令牌。在这种情况下,您可以使用 axios-retry 来处理错误重试。
  • 登录后,启动异步任务以小于令牌过期的时间间隔更新令牌。在我们的示例中为 3400 毫秒。因此 api 来自您的网络的调用永远不会失败

建议

在后端层执行 access_token 和 refresh_token 交换,而不是在前端 (ajax) 层。

因此攻击者永远不会知道您的端点以获取令牌或刷新它们。