jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?相关的知识,希望对你有一定的参考价值。

jwt一般都会有2个token,一个access_token和一个refresh_token,我看资料说,access_token是我们平时请求的时候携带的身份凭证,当access_token过期时,可以使用refresh_token来刷新access_token,access_token有效期短,refresh_token有效期长。我觉得这是不是多此一举,直接把access_token的有效期设置长一点不就好了,请问为啥他非得搞2个token呢?

access_token使用频率高,容易泄露,有效期风险就小。refresh_token使用频率低,泄露风险小。另外,不是必须要有两个token吧? 参考技术A jwt包含了足够的信息,且可以由客户端自己验证是否有效,甚至极端情况下,服务端签发不需要存储它。
令牌就是token,简单说就是一个字符串,用户登录后,生成一个随机串作为key,value就是User对象信息,value存储在服务端,把token下发给客户端,但是客户端每次都要让服务端验证这个token是否有效。

令牌刷新时的部分 JWT 令牌

【中文标题】令牌刷新时的部分 JWT 令牌【英文标题】:Partial JWT token at token refresh 【发布时间】:2019-07-01 16:05:53 【问题描述】:

在微服务架构中,我们使用来自 keycloak 的 JWT 令牌。现在我们想要获得第二个权限更少的访问令牌(更少的声明/更少的角色)。用例是:新的访问令牌应该允许其所有者访问文档存储中的一个文档。为什么?限制某人在窃取此令牌时可能造成的损害。

理想情况下,我们可以通过特殊的 refresh_token 调用获得第二个令牌(持有刷新令牌的用户有权获得完全访问令牌,因此他也应该能够获得部分访问令牌)。我们怎么能这样做?

使用范围似乎不起作用:给定范围列表仅在登录时评估(因此在刷新令牌时,我不能采用范围列表)。

我也尝试了解https://www.keycloak.org/docs/latest/authorization_services/index.html#_service_overview 或RPT。但不幸的是,我缺少一些文档(我的尝试失败了)。

还有其他想法吗?或者甚至是一个展示如何做到这一点的示例?

稍后编辑以使我关于 RPT 的问题更加明确: https://www.keycloak.org/docs/latest/authorization_services/index.html#_service_overview 说:

... Keycloak 授权服务提供对 OAuth2 的扩展,以 允许基于所有策略的处理来发布访问令牌 与被请求的资源或范围相关联。这意味着 资源服务器可以强制访问其受保护的资源,基于 由服务器授予并由访问令牌持有的权限。在钥匙斗篷里 授权服务具有权限的访问令牌称为 Requesting Party Token 简称 RPT。

这种具有权限的访问令牌可以用于我们的目标吗?

在我的实验中,我可以通过 grant_type=urn:ietf:params:oauth:grant-type:uma-ticket 获得令牌。但是有一些问题:

我不得不更改 keycloak 中的一些设置以启用权限(在它会说“客户端不支持权限”之前)。进行这些更改后,我的正常登录调用将不再起作用(我可以在我的令牌仍然有效时进行测试)。我不得不修改我的 keycloak 配置才能继续工作。

我不太了解用于此功能的权限模型

端到端的例子会很有用(Keycloak 文档中的例子有点抽象)。

【问题讨论】:

这是一个有趣的问题+1。我根本不知道密钥斗篷,但是是什么阻止您使用类似于您用来生成初始 JWT 的代码?顺便说一句,您可能已经知道,在为文档颁发新的访问令牌之前,您需要使之前的 JWT 无效。否则,旧的仍然存在。 “是什么阻止了你使用类似于你用来生成初始 JWT 的代码” 部分令牌应该在登录后的某个时间生成(我不想存储登录凭据)。 为了提高应用程序的安全级别,我会: - 使用较短的访问令牌生命周期值 - 在 SSL 上使用 HTTP - 限制用户会话超时 您正在考虑的内容意味着额外的复杂层(如据我所知)这可能涉及自己编写安全相关代码以扩展 OIDC 协议,这可能会带来更多风险。 @XtremeBiker:感谢您列出的良好做法(我们已经在应用它们)。您是否暗示我们想要做的事情在 Keycloak 中是不可能的? 不客气!这是使用此工具进行资源配置功能强大的一个示例,并不适合您的具体情况。在您的情况下,您需要应用程序为特定用户分配资源,而不是 Alice(请参阅文档中的 8.4 chapter)。 【参考方案1】:

我已进入文档,通过保护您的资源服务器(您的应用程序)以充当受 UMA 保护的资源服务器,可以实现您想要的。 Here you have 一个基本的例子,可以用这个来实现:

Keycloak 是一个符合 UMA 2.0 的授权服务器,它提供 大多数 UMA 功能。

例如,假设用户 Alice(资源所有者)使用 网上银行服务(资源服务器)来管理他的银行账户 (资源)。有一天,爱丽丝决定为鲍勃开设她的银行账户 (请求方),会计专业人士。然而,鲍勃应该 只能查看(范围)Alice 的帐户。

作为资源服务器,网上银行服务必须能够 保护爱丽丝的银行账户。为此,它依赖于 Keycloak 资源 注册端点在服务器中创建资源代表 爱丽丝的银行账户。

此时,如果 Bob 尝试访问 Alice 的银行账户,则访问 将被拒绝。网上银行服务定义了一些默认的 银行账户政策。其中之一是只有所有者,在 在这种情况下,Alice 可以访问她的银行帐户。

然而,网上银行服务也尊重爱丽丝的隐私 允许她更改银行账户的特定政策。之一 她可以改变的这些政策是定义哪些人是 允许查看她的银行账户。为此,网上银行服务 依靠 Keycloak 为 Alice 提供一个可以选择的空间 个人及其被允许访问的操作(或数据)。 Alice 可以随时撤销访问权限或授予其他权限 给鲍勃。

然后使用策略执行器来触发此保护:

如果资源服务器受到策略执行器的保护,它会响应 基于承载的权限的客户端请求 令牌。通常,当您尝试使用 无权访问受保护的不记名令牌 资源,资源服务器以 401 状态码和 WWW-Authenticate 标头。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="$realm",
    as_uri="https://$host:$post/auth/realms/$realm",
    ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"

这里有两个部分你需要做。第一个是 add policy enforcement 获取您想要保护的应用程序路径。然后,酱汁来了,你需要configure the UMA part。 UMA 的优点在于它在授权过程中添加了一个额外的票证系统,并且该票证是按资源分配的(实际上,它们是在您尝试访问受保护的资源时分配的)。

客户端在不发送 RPT 的情况下请求受保护的资源

curl -X GET \
  http://$host:8080/my-resource-server/resource/1bfdfe78-a4e1-4c2d-b142-fc92b75b986f

资源服务器将响应发送回客户端,其中包含 权限票证和 as_uri 参数,其中包含 a 的位置 Keycloak 服务器应该发送票证以便获取 一个RPT。资源服务器以许可票响应

HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="$realm",
    as_uri="https://$host:$post/auth/realms/$realm",
    ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"

因此,客户端请求资源,并获得一张带有 Keycloak 服务器位置的票证,以便将该票证换成 RPT。这是客户端发布令牌端点,以便获取 RPT:

curl -X POST \
  http://$host:$port/auth/realms/$realm/protocol/openid-connect/token \
  -H "Authorization: Bearer $access_token" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "ticket=$permission_ticket \
  --data "submit_request=true"

这将为您提供仅对访问您第一次询问的资源有效的 RPT。这么说:


  "authorization": 
      "permissions": [
        
          "resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7",
          "resource_set_name": "Hello World Resource"
        
      ]
  ,
  "jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405",
  "exp": 1464906971,
  "nbf": 0,
  "iat": 1464906671,
  "sub": "f1888f4d-5172-4359-be0c-af338505d86c",
  "typ": "kc_ett",
  "azp": "hello-world-authz-service"

您还需要manage users access to their resources。此处使用管理 UI 完成,但您可能需要从应用程序正确配置它,调用 Keycloak API。

【讨论】:

以上是关于jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 自动刷新JWT Token #yyds干货盘点#

具有长 TTL 的引用令牌和刷新令牌+短寿命 JWT 有啥区别?

JWT, 为啥需要刷新令牌?

刷新令牌是不是需要过期的 JWT 才能创建新的访问令牌?

如何以及为啥使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭]

JWT refresh_token 包含啥?