KeyCloak 刷新外部 IDP 令牌

6
我们正在使用KeyCloak身份代理来将身份验证联合到外部IDP。身份提供者的类型为OpenID Connect v1.0。此外,我们正在使用OIDC授权代码流与PKCE。
根据以下文档,我们能够成功地从外部IDP检索令牌: https://www.keycloak.org/docs/latest/server_admin/#retrieving-external-idp-tokens 然而,当用户代理使用“refresh_token”授予刷新KeyCloak令牌时,外部IDP的令牌没有被刷新。KeyCloak在这个主题上提供了非常少的文档。
有人知道如何刷新来自外部IDP的令牌吗?
更新:我已经向KeyCloak社区发起了问题 https://github.com/keycloak/keycloak-community/issues/277

我们还没有找到一个完美的解决方案。目前我们是在KeyCloak外部从IDP刷新令牌。然而,这种方法有一些限制,因为我们依赖于IDP不撤销原始的刷新令牌。 - Ayondeep Datta
非常感谢您的回复!这正是我心中所想的解决方法。但目前我还有些犹豫不决 :) - Mario Eis
如果您找到更好的解决方案,请告诉我们 :) - Ayondeep Datta
链接 https://github.com/keycloak/keycloak-community/issues/277 已失效。 - Sébastien Helbert
1
我也无法访问我在此主题上开启的KeyCloak问题 (https://github.com/keycloak/keycloak-community/issues/277)。看起来他们从Github上撤下了问题部分。我之前也在Keycloak论坛上创建了一个主题,但是我没有收到他们团队的任何回复 (https://keycloak.discourse.group/t/keycloak-does-not-refresh-external-idp-token/11261)。我不确定现在联系KeyCloak团队的最佳方式是什么。似乎这是一个更加封闭的事务。 - Ayondeep Datta
显示剩余3条评论
3个回答

2
@Hawk提出的解决方案涉及到一个不同的API - Token Exchange - 可用于在KeyCloak上检索(甚至伪造)令牌。在您可以交换的所有不同令牌中,您可以从配置的身份提供者中检索令牌,这是我们最终使用的方法。
长话短说,您正在使用的“检索外部IDP令牌”功能不会为您刷新令牌:如果您计划使用它,您将不得不检索刷新令牌并自己生成新的访问令牌,这很不幸,因为这将迫使您在应用程序中拥有客户端/秘密ID提供者的ID。
相反,Token Exchange API将为您刷新令牌。您可以通过发出此请求轻松检索IP访问令牌(示例使用python,您显然可以使用任何其他语言):
    response = requests.post(
        f"{ID_PROVIDER_HOST}/auth/realms/{REALM}/protocol/openid-connect/token",
        data={
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
            "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
            "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
            "requested_issuer": IDENTITY_PROVIDER_ALIAS,
            "subject_token": access_token,
        },
    )

你需要进行一些配置:首先,Token Exchange 在当前 KeyCloak 版本(17)中处于“技术预览”状态,并且默认情况下未启用;请参阅 KeyCloak 文档以了解如何启用它。
然后,您需要启用客户端以交换 IP 令牌:从您领域的管理面板:
  • 从侧边栏中选择“身份提供者”;
  • 选择要从中检索令牌的身份提供者;
  • 选择“权限”选项卡;
  • 启用权限,如果尚未启用;
  • 单击“令牌交换”
  • 在“应用策略”表中选择“创建类型为“客户端”的策略”
  • 给策略命名,并选择您想要能够检索访问令牌的客户端。

在外部令牌过期后,如果出现错误,则会收到未捕获的服务器错误:java.lang.RuntimeException: com.fasterxml.jackson.core.JsonParseException:无法识别令牌“HTTP”:预期是(JSON字符串、数字、数组、对象或标记“null”、“true”或“false”)在[Source:(String)“HTTP Basic:Access denied. - Ritesh Khatri

2
Keycloak 保留上游 IdP 的访问令牌和刷新令牌。当您执行令牌交换时,如果访问令牌已过期但刷新令牌尚未过期,则会刷新令牌。请参见此处:https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java#L186-L187 简单地说,您需要更频繁地调用令牌交换端点,以使其刷新外部刷新令牌的时间不超过有效期。根据您的实现方式,您可以通过多种方式利用它。例如,我将我的访问令牌 ttl 设置得比外部 IdP 的刷新令牌 ttl 短,并且我有一个机密客户端,在每次看到新的访问令牌时都会调用令牌交换端点,虽然不是最佳解决方案,但总比眼里插着一根棍子好。
我不知道为什么 Keycloak 开发人员不在您执行 Keycloak 发行的令牌刷新时刷新任何外部令牌。他们是聪明的人,所以我相信有理由,但到目前为止,我还没有能够弄清楚。我一直在考虑扩展现有的 OIDCIdentityProvider 来实现这一点,但除非我了解自己要做什么,否则我不想打开这个罐子。如果有人有任何见解,我将不胜感激。

感谢@Hawk提供的解决方案。然而,我不确定这是否解决了核心问题,或者我可能遗漏了什么。问题不在于获取外部IdP令牌(access & refresh),这如Keycloak文档中的“检索外部IdP令牌”节所述完美运作。问题是当在代理领域执行OAuth2刷新令牌授权时,外部IdP刷新令牌不会被更新。 - Ayondeep Datta
请查看上面链接的代码,当您执行外部令牌交换时,如果外部刷新令牌未过期,则keycloak将刷新外部访问令牌。 - Hawk

0
抱歉重新激活一个已经停止的讨论。我可以确认你是在说令牌交换会自动为我们续订令牌吗?还是我们需要调用令牌端点才能实现这一点?或者它根本不会自动续订?

这并没有回答问题。一旦你有足够的声望,你就可以评论任何帖子;相反,提供不需要提问者澄清的答案。- 来自审核 - Aaron Meese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接