第 5 章 身份代理 API


红帽构建的 Keycloak 可以将身份验证委托给父 IDP 以进行登录。其中一个典型的示例是您希望用户通过一个社交供应商(如 Facebook 或 Google)登录。您还可以将现有帐户链接到代理的 IDP。本节论述了应用程序可以与身份代理相关的一些 API。

5.1. 检索外部 IDP 令牌

红帽构建的 Keycloak 允许您使用外部 IDP 存储来自身份验证过程的令牌和响应。为此,您可以在 IDP 的设置页面中使用 Store Token 配置选项。

应用程序代码可以检索这些令牌和响应,以拉取额外的用户信息,或者安全地调用外部 IDP 上的请求。例如,应用程序可能希望使用 Google 令牌在其他 Google 服务和 REST API 上调用。要检索特定身份提供程序的令牌,您需要发送请求,如下所示:

GET /realms/{realm-name}/broker/{provider_alias}/token HTTP/1.1
Host: localhost:8080
Authorization: Bearer <KEYCLOAK ACCESS TOKEN>
Copy to Clipboard Toggle word wrap

应用程序必须使用红帽构建的 Keycloak 进行身份验证,并收到访问令牌。此访问令牌需要设置 代理 客户端级角色 read-token。这意味着,用户必须拥有此角色的角色映射,并且客户端应用程序必须在其范围内拥有该角色。在这种情况下,如果您在红帽构建的 Keycloak 中访问受保护的服务,您需要在用户身份验证过程中发送由红帽构建 Keycloak 发布的访问令牌。在代理配置页面中,您可以通过打开 Stored Tokens Readable 开关,自动将此角色分配给新导入的用户。

这些外部令牌可以通过提供程序再次登录或使用启动的帐户链接 API 重新建立。

<_client-initiated-account-linking><title>客户端启动帐户链接</title>

有些应用程序希望与 Facebook 等社交提供商集成,但不想通过这些社交提供商登录。红帽 Keycloak 的构建提供了基于浏览器的 API,应用程序可以使用该 API 将现有用户帐户链接到特定的外部 IDP。这称为客户端发起的帐户链接。帐户链接只能由 OIDC 应用程序启动。

它的工作方式是,应用程序将用户的浏览器转发到红帽构建的 Keycloak 服务器的 URL,要求其要将用户的帐户链接到特定的外部提供程序(如bookbook)。服务器使用外部提供程序启动登录。浏览器从外部提供程序登录,并重定向到服务器。服务器建立链接,并通过确认重定向到应用程序。

在启动此协议前,客户端应用程序必须满足一些条件:

  • 必须在管理控制台中为用户域配置并启用所需的身份提供程序。
  • 用户必须具有 account.manage-accountaccount.manage-account-links 角色映射。
  • 必须在其访问令牌内授予这些角色的范围

协议由 应用程序发起的操作(AIA) 实现。如果您希望在客户端应用程序中进行身份验证的用户,要链接到身份提供程序,请将参数 kc_action 与值 idp_link:<identity-provider-alias > 附加到 OIDC 身份验证 URL,并将用户重定向到此 URL。例如,要请求链接到别名 my-oidc-provider 的身份提供程序,请附加参数,例如:

kc_action=idp_link:my-oidc-provider
Copy to Clipboard Toggle word wrap

1. 刷新外部令牌

如果您使用通过登录到供应商(如 Facebook 或 GitHub 令牌)生成的外部令牌,您可以通过重新发起帐户链接 API 来刷新此令牌。

2. 传统客户端启动帐户链接

警告

传统客户端启动帐户链接使用不基于 AIA 的自定义协议。如果您使用这个协议,请考虑将客户端应用程序迁移到上述基于 AIA 的协议,因为传统客户端启动的帐户链接可能会在以后的 Red Hat build of Keycloak 版本中删除。

除了上面的 preconditions 外,传统客户端启动帐户链接还有另一个条件:

  • 用户帐户必须通过 OIDC 协议以现有用户登录
  • 应用必须有权访问其访问令牌,因为它需要其中的信息来生成重定向 URL。

若要启动登录,应用必须结构化 URL,并将用户的浏览器重定向到此 URL。URL 类似如下:

/{auth-server-root}/realms/{realm-name}/broker/{provider}/link?client_id={id}&redirect_uri={uri}&nonce={nonce}&hash={hash}
Copy to Clipboard Toggle word wrap

以下是每个路径和查询参数的描述:

provider
这是您在管理控制台 Identity Provider 部分中定义的外部 IDP 的供应商别名。
client_id
这是应用程序的 OIDC 客户端 ID。在 admin 控制台中将应用程序注册为客户端时,您必须指定此客户端 ID。
redirect_uri
这是您要在帐户链接建立后要重定向到的应用程序回调 URL。它必须是有效的客户端重定向 URI 模式。换句话说,它必须与您在管理控制台中注册客户端时定义的有效 URL 模式之一匹配。
nonce
这是应用程序必须生成的随机字符串
hash
这是一个 Base64 URL 编码哈希。此哈希由 Base64 URL 编码为 一个非ce + token.getSessionState () + token.getIssuedFor () + provider 的 SHA_256 哈希生成。令牌变量从 OIDC 访问令牌获取。您基本上是对随机非ce、用户会话 ID、客户端 ID 和您要访问的身份提供商别名进行哈希处理。

下面是生成 URL 以建立帐户链接的 Java Servlet 代码示例。

   KeycloakSecurityContext session = (KeycloakSecurityContext) httpServletRequest.getAttribute(KeycloakSecurityContext.class.getName());
   AccessToken token = session.getToken();
   String clientId = token.getIssuedFor();
   String nonce = UUID.randomUUID().toString();
   MessageDigest md = null;
   try {
      md = MessageDigest.getInstance("SHA-256");
   } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
   }
   String input = nonce + token.getSessionState() + clientId + provider;
   byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
   String hash = Base64Url.encode(check);
   request.getSession().setAttribute("hash", hash);
   String redirectUri = ...;
   String accountLinkUrl = KeycloakUriBuilder.fromUri(authServerRootUrl)
                    .path("/realms/{realm-name}/broker/{provider}/link")
                    .queryParam("nonce", nonce)
                    .queryParam("hash", hash)
                    .queryParam("client_id", clientId)
                    .queryParam("redirect_uri", redirectUri).build(realm, provider).toString();
Copy to Clipboard Toggle word wrap

为什么包含此哈希?我们这样做的目的是保证身份验证服务器可以保证客户端应用程序发起请求,而其他相关应用程序都没有随机要求用户帐户链接到特定提供程序。身份验证服务器将首先通过检查登录时设置的 SSO cookie 来检查用户是否已登录。然后,它将尝试根据当前登录来重新生成哈希,并将其与应用程序发送的哈希匹配。

链接帐户后,身份验证服务器将重定向到 redirect_uri。如果提供链接请求存在问题,则 auth 服务器可能会或可能无法重定向到 redirect_uri。浏览器可能只是在错误页面结束,而不是重新重定向到应用。如果存在错误条件,并且 auth 服务器会足够安全重定向到客户端应用,则额外的 错误 查询参数将附加到 redirect_uri 中。

警告

虽然此 API 保证应用程序启动请求,但它不会完全防止 CSRF 攻击此操作。应用程序仍负责保护 CSRF 攻击目标。

</_client-initiated-account-linking>
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat