Keycloak 功能和概念

Keycloak 是一个用于 Web 应用程序和 RESTful Web 服务的单点登录解决方案。Keycloak 的目标是简化安全性,以便应用程序开发人员可以轻松地保护他们在组织中部署的应用程序和服务。开发人员通常需要自己编写的安全性功能开箱即用,并且可以轻松地根据您组织的个性化需求进行定制。Keycloak 为登录、注册、管理和帐户管理提供可自定义的用户界面。您还可以使用 Keycloak 作为集成平台,将其连接到现有的 LDAP 和 Active Directory 服务器。您还可以将身份验证委派给 Facebook 和 Google 等第三方身份提供程序。

功能

Keycloak 提供以下功能

  • 浏览器应用程序的单点登录和单点注销。

  • OpenID Connect 支持。

  • OAuth 2.0 支持。

  • SAML 支持。

  • 身份代理 - 使用外部 OpenID Connect 或 SAML 身份提供程序进行身份验证。

  • 社交登录 - 启用使用 Google、GitHub、Facebook、Twitter 和其他社交网络登录。

  • 用户联合 - 从 LDAP 和 Active Directory 服务器同步用户。

  • Kerberos 桥接 - 自动验证已登录到 Kerberos 服务器的用户的身份。

  • 用于集中管理用户、角色、角色映射、客户端和配置的管理员控制台。

  • 允许用户集中管理其帐户的帐户控制台。

  • 主题支持 - 自定义所有面向用户的页面,以与您的应用程序和品牌形象相集成。

  • 双因素身份验证 - 支持通过 Google Authenticator 或 FreeOTP 进行 TOTP/HOTP 验证。

  • 登录流程 - 可选的用户自助注册、密码恢复、电子邮件验证、要求密码更新等。

  • 会话管理 - 管理员和用户自己可以查看和管理用户会话。

  • 令牌映射器 - 按照您希望的方式将用户属性、角色等映射到令牌和声明中。

  • 每个域、应用程序和用户的 Not-before 撤销策略。

  • CORS 支持 - 客户端适配器内置了对 CORS 的支持。

  • 服务提供商接口 (SPI) - 许多 SPI 可用于自定义服务器的各个方面。身份验证流程、用户联合提供商、协议映射器等等。

  • 支持任何具有 OpenID Connect Relying Party 库或 SAML 2.0 服务提供商库的平台/语言。

Keycloak 基本操作

Keycloak 是一个独立的服务器,您可以在您的网络上管理它。应用程序配置为指向此服务器并由此服务器保护。Keycloak 使用开放协议标准(如 OpenID ConnectSAML 2.0)来保护您的应用程序。浏览器应用程序将用户的浏览器从应用程序重定向到 Keycloak 身份验证服务器,用户在其中输入其凭据。此重定向非常重要,因为用户与应用程序完全隔离,并且应用程序永远不会看到用户的凭据。相反,应用程序会获得经过加密签名的身份令牌或断言。这些令牌可以包含身份信息,如用户名、地址、电子邮件和其他个人资料数据。它们还可以包含权限数据,以便应用程序可以做出授权决策。这些令牌还可以用于对基于 REST 的服务进行安全调用。

核心概念和术语

在尝试使用 Keycloak 保护您的 Web 应用程序和 REST 服务之前,请考虑以下核心概念和术语。

用户

用户是能够登录到您的系统的实体。他们可以拥有与其关联的属性,如电子邮件、用户名、地址、电话号码和生日。他们可以被分配到组成员资格并被分配特定的角色。

身份验证

识别和验证用户的过程。

授权

授予用户访问权限的过程。

凭据

凭据是 Keycloak 用于验证用户身份的数据片段。一些示例包括密码、一次性密码、数字证书,甚至是指纹。

角色

角色标识用户的类型或类别。Adminusermanageremployee 都是组织中可能存在的典型角色。应用程序通常将访问权限和许可权分配给特定角色,而不是单个用户,因为处理用户可能过于细粒度且难以管理。

用户角色映射

用户角色映射定义角色和用户之间的映射。一个用户可以与零个或多个角色关联。此角色映射信息可以封装到令牌和断言中,以便应用程序可以决定对其管理的各种资源的访问权限。

复合角色

复合角色是可以与其他角色关联的角色。例如,superuser 复合角色可以与 sales-adminorder-entry-admin 角色关联。如果用户映射到 superuser 角色,他们也会继承 sales-adminorder-entry-admin 角色。

组管理用户组。可以为组定义属性。您也可以将角色映射到组。成为组成员的用户将继承该组定义的属性和角色映射。

域管理一组用户、凭据、角色和组。用户属于并登录到一个域。域彼此隔离,并且只能管理和验证他们控制的用户。

客户端

客户端是可以请求 Keycloak 验证用户身份的实体。通常,客户端是想要使用 Keycloak 来保护自身并提供单点登录解决方案的应用程序和服务。客户端也可以是只想请求身份信息或访问令牌的实体,以便他们可以安全地调用网络上由 Keycloak 保护的其他服务。

客户端适配器

客户端适配器是您安装到应用程序环境中的插件,以便能够与 Keycloak 通信并受其保护。Keycloak 具有许多适用于不同平台的适配器,您可以下载这些适配器。还有您可以为我们未涵盖的环境获得的第三方适配器。

同意

同意是指当您作为管理员希望用户在客户端参与身份验证过程之前向客户端授予权限时。在用户提供其凭据后,Keycloak 将弹出一个屏幕,标识请求登录的客户端以及向用户请求的身份信息。用户可以决定是否授予请求。

客户端作用域

注册客户端时,您必须为该客户端定义协议映射器和角色作用域映射。存储客户端作用域通常很有用,通过共享一些常用设置,可以更轻松地创建新客户端。这对于根据 scope 参数的值有条件地请求某些声明或角色也很有用。Keycloak 为此提供了客户端作用域的概念。

客户端角色

客户端可以定义特定于它们的角色。这基本上是专用于客户端的角色命名空间。

身份令牌

提供有关用户身份信息的令牌。OpenID Connect 规范的一部分。

访问令牌

可以作为 HTTP 请求的一部分提供的令牌,该令牌授予对正在调用的服务的访问权限。这是 OpenID Connect 和 OAuth 2.0 规范的一部分。

断言

有关用户的信息。这通常与包含在 SAML 身份验证响应中的 XML blob 有关,该响应提供了有关已验证用户的身份元数据。

服务帐户

每个客户端都有一个内置的服务帐户,允许它获取访问令牌。

直接授权

客户端代表用户通过 REST 调用获取访问令牌的一种方式。

协议映射器

对于每个客户端,您都可以定制存储在 OIDC 令牌或 SAML 断言中的声明和断言。您可以通过创建和配置协议映射器来为每个客户端执行此操作。

会话

当用户登录时,会创建一个会话来管理登录会话。会话包含诸如用户何时登录以及哪些应用程序在该会话期间参与了单点登录的信息。管理员和用户都可以查看会话信息。

用户联合提供商

Keycloak 可以存储和管理用户。通常,公司已经拥有 LDAP 或 Active Directory 服务,用于存储用户和凭据信息。您可以将 Keycloak 指向这些外部存储以验证凭据并提取身份信息。

身份提供商

身份提供商 (IDP) 是一种可以验证用户身份的服务。Keycloak 就是一个 IDP。

身份提供商联合

Keycloak 可以配置为将身份验证委派给一个或多个 IDP。通过 Facebook 或 Google 进行社交登录是身份提供商联合的一个示例。您还可以连接 Keycloak 以将身份验证委派给任何其他 OpenID Connect 或 SAML 2.0 IDP。

身份提供商映射器

在执行 IDP 联合时,您可以将传入的令牌和断言映射到用户和会话属性。这有助于您将身份信息从外部 IDP 传播到请求身份验证的客户端。

必需操作

必需操作是用户在身份验证过程中必须执行的操作。用户在完成这些操作之前将无法完成身份验证过程。例如,管理员可以安排用户每月重置其密码。将为所有这些用户设置 update password 必需操作。

身份验证流程

身份验证流程是用户在与系统的某些方面交互时必须执行的工作流程。登录流程可以定义所需的凭据类型。注册流程定义用户必须输入的个人资料信息以及是否必须使用 reCAPTCHA 等来过滤掉机器人程序。凭据重置流程定义用户在重置密码之前必须执行的操作。

事件

事件是管理员可以查看和挂钩的审计流。

主题

Keycloak 提供的每个屏幕都由一个主题支持。主题定义 HTML 模板和样式表,您可以根据需要覆盖它们。

创建第一个管理员

安装 Keycloak 后,您需要一个管理员帐户,该帐户可以充当超级管理员,并具有管理 Keycloak 的完全权限。使用此帐户,您可以登录到 Keycloak 管理控制台,您可以在其中创建域和用户,并注册由 Keycloak 保护的应用程序。

在本地主机上创建帐户

如果您的服务器可以从 localhost 访问,请执行以下步骤。

步骤
  1. 在 Web 浏览器中,转到 https://#:8080 URL。

  2. 提供您可以记住的用户名和密码。

    欢迎页面

    Welcome page

远程创建帐户

如果您无法从 localhost 地址访问服务器,或者只想从命令行启动 Keycloak,请使用 KC_BOOTSTRAP_ADMIN_USERNAMEKC_BOOTSTRAP_ADMIN_PASSWORD 环境变量来创建初始管理员帐户。

例如

export KC_BOOTSTRAP_ADMIN_USERNAME=<username>
export KC_BOOTSTRAP_ADMIN_PASSWORD=<password>

bin/kc.[sh|bat] start

配置域

一旦您拥有管理员控制台的管理员帐户,您就可以配置域。域是您管理对象(包括用户、应用程序、角色和组)的空间。用户属于并登录到一个域。一个 Keycloak 部署可以定义、存储和管理任意数量的域,只要数据库中有足够的空间。

使用管理控制台

您可以在 Keycloak 管理控制台中配置域并执行大多数管理任务。

先决条件

要使用管理控制台,您需要一个管理员帐户。

  • 如果不存在管理员,请参阅创建第一个管理员

  • 如果存在其他管理员,请让管理员提供具有管理域权限的帐户。

步骤
  1. 转到管理控制台的 URL。

    例如,对于 localhost,请使用此 URL:https://#:8080/admin/

  2. 输入您在欢迎页面上创建的用户名和密码,或通过环境变量创建的用户名和密码,如创建初始管理员用户中所述。

    登录页面

    Login page

    此操作将显示管理控制台。

    管理控制台

    Admin Console

  3. 注意您可以使用的菜单和其他选项

    • 单击当前域以查看是否有其他域可供管理。

    • 单击创建域以创建另一个您可以管理的域。

    • 单击右上角的列表以查看您的帐户或注销。

  4. 单击菜单中的域设置以查看此域的字段和选项。

    单击问号 ? 图标以显示字段的定义,例如前端 URL

    域设置

    Realm settings

从管理控制台导出的文件不适合备份或服务器之间的数据传输。只有启动时导出才适合备份或服务器之间的数据传输。

主 Realm

在管理控制台中,存在两种类型的 realm

  • Master realm - 此 realm 是您首次启动 Keycloak 时为您创建的。它包含您在首次登录时创建的管理员帐户。仅使用 master realm 来创建和管理系统中的 realm。

  • Other realms - 这些 realm 由 master realm 中的管理员创建。在这些 realm 中,管理员管理您组织中的用户以及他们需要的应用程序。应用程序归用户所有。

Realm 和应用程序

Realms and applications

Realm 彼此隔离,并且只能管理和验证他们控制的用户。遵循此安全模型有助于防止意外更改,并遵循传统,即仅允许用户帐户访问成功完成当前任务所需的特权和权力。

附加资源
  • 如果您想禁用 master realm 并在您创建的任何新 realm 中定义管理员帐户,请参阅 Dedicated Realm Admin Consoles。每个 realm 都有其自己专用的管理控制台,您可以使用本地帐户登录。

创建 realm

您创建 realm 以提供管理空间,您可以在其中创建用户并授予他们使用应用程序的权限。首次登录时,您通常在 master realm 中,这是您从中创建其他 realm 的顶级 realm。

在决定您需要哪些 realm 时,请考虑您希望为您的用户和应用程序提供的隔离类型。例如,您可以为贵公司的员工创建一个 realm,并为您的客户创建一个单独的 realm。您的员工将登录到员工 realm,并且只能访问内部公司应用程序。客户将登录到客户 realm,并且只能与面向客户的应用程序进行交互。

步骤
  1. 在管理控制台中,单击“当前 realm”旁边的“创建 Realm”。

  2. 输入 realm 的名称。

  3. 单击“创建”。

    创建 realm

    Create realm

    当前 realm 现在设置为您刚刚创建的 realm。您可以通过单击菜单中的 realm 名称在 realm 之间切换。

为 realm 配置 SSL

每个 realm 都有一个关联的 SSL 模式,该模式定义了与 realm 交互的 SSL/HTTPS 要求。与 realm 交互的浏览器和应用程序必须遵守 SSL 模式定义的 SSL/HTTPS 要求,否则它们无法与服务器交互。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击“常规”选项卡。

    常规选项卡

    General Tab

  3. 将“需要 SSL”设置为以下 SSL 模式之一

    • 外部请求 - 只要用户坚持使用私有 IPv4 地址(例如 localhost127.0.0.110.x.x.x192.168.x.x172.16.x.x)或 IPv6 链路本地地址和唯一本地地址,用户就可以在没有 SSL 的情况下与 Keycloak 交互。如果您尝试从非私有 IP 地址在没有 SSL 的情况下访问 Keycloak,您将收到错误。

    • - Keycloak 不需要 SSL。此选项仅适用于您在进行实验且不计划支持此部署的开发环境。

    • 所有请求 - Keycloak 要求所有 IP 地址都使用 SSL。

为 realm 配置电子邮件

Keycloak 向用户发送电子邮件以验证他们的电子邮件地址、在他们忘记密码时或当管理员需要接收有关服务器事件的通知时。要使 Keycloak 能够发送电子邮件,您需要为 Keycloak 提供您的 SMTP 服务器设置。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击“电子邮件”选项卡。

    电子邮件选项卡

    Email Tab

  3. 填写字段并根据需要切换开关。

模板
发件人

发件人”表示用于发送电子邮件的 From SMTP 标头的地址。

发件人显示名称

发件人显示名称”允许配置用户友好的电子邮件地址别名(可选)。如果未设置,则将在电子邮件客户端中显示纯 发件人 电子邮件地址。

回复至

回复至”表示用于发送邮件的 Reply-To SMTP 标头的地址(可选)。如果未设置,则将使用纯 发件人 电子邮件地址。

回复至显示名称

回复至显示名称”允许配置用户友好的电子邮件地址别名(可选)。如果未设置,则将显示纯 回复至 电子邮件地址。

邮件信封发件人

邮件信封发件人”表示用于发送邮件的 Return-Path SMTP 标头的 退回地址(可选)。

连接和身份验证
主机

主机”表示用于发送电子邮件的 SMTP 服务器主机名。

端口

端口”表示 SMTP 服务器端口。

加密

勾选其中一个复选框以支持发送用于恢复用户名和密码的电子邮件,特别是当 SMTP 服务器位于外部网络上时。您很可能需要将“端口”更改为 465,这是 SSL/TLS 的默认端口。

身份验证

如果您的 SMTP 服务器需要身份验证,请将此开关设置为“开启”。

用户名

所有身份验证机制都需要用户名。

身份验证类型

选择身份验证的类型:“password”或“token”。

密码

仅当选择“身份验证类型”为“password”时才需要。提供 密码。“密码”字段的值可以引用来自外部 vault 的值。

身份验证令牌 URL

仅当选择“身份验证类型”为“token”时才需要。提供用于通过客户端凭据授权获取令牌的 身份验证令牌 URL

身份验证令牌范围

仅当选择“身份验证类型”为“token”时才需要。提供用于从 身份验证令牌 URL 获取令牌的 身份验证令牌范围

身份验证令牌客户端 ID

仅当选择“身份验证类型”为“token”时才需要。提供用于从 身份验证令牌 URL 获取令牌的 身份验证客户端 ID

身份验证令牌客户端密钥

仅当选择“身份验证类型”为“token”时才需要。提供用于验证客户端身份以从 身份验证令牌 URL 获取令牌的 身份验证客户端密钥。“身份验证客户端密钥”字段的值可以引用来自外部 vault 的值。

使用第三方供应商进行 XOAUTH2 电子邮件配置

以下部分包含关于如何配置 Keycloak 电子邮件设置以将 XOAUTH2 身份验证与一些已知的第三方软件 SMTP 服务器一起使用的提示。

本节由 Keycloak 社区贡献。由于 Keycloak 核心团队没有测试第三方提供商的手段,因此按原样提供。如果您发现本文档已过时或不完整,请贡献以改进它。
Microsoft Azure 和 Office365 的配置

Microsoft Azure 允许使用客户端密钥的“客户端凭据授权”来收集访问令牌。Microsoft Office365 支持使用 XOAUTH2 的 SMTP 来使用收集的令牌进行身份验证。

相关 Microsoft 文档的链接

以下用于设置 Keycloak 以使用 Azure 和 Office365 发送电子邮件的方法已通过测试验证。根据您的环境,可能还有其他变体可以实现相同的目的。

发件人

<some>@<domain>

主机

smtp.office365.com

端口

587

加密

选中“启动 TLS”

用户名

<some>@<domain>(可能与发件人值相同或不同)

身份验证令牌 URL

https://login.microsoftonline.com/<TenantID>/oauth2/v2.0/token

将 TenantID 替换为您的 Microsoft 租户的 ID(通常是 UUID),在 Azure 中,或者只需从 Azure 控制台中显示的端点列表中复制令牌 URL。

身份验证令牌范围

https://outlook.office.com/.default

身份验证令牌客户端 ID

<ApplicationId>

将 ApplicationId 替换为您的应用程序在 Azure 中的 ID(通常是 UUID)。

身份验证令牌客户端密钥

<Secret configured>

Google Mail 的配置

Keycloak 尚不支持此功能,因为 Google 不允许客户端凭据授权使用客户端密钥。

AWS 的配置

AWS-SMTP 服务不支持 XOAUTH2。AWS 服务需要使用密码。

配置主题

对于给定的 realm,您可以使用主题更改 Keycloak 中任何 UI 的外观。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击“主题”选项卡。

    主题选项卡

    Themes tab

  3. 为每个 UI 类别选择您想要的主题,然后单击“保存”。

    登录主题

    用户名密码输入、OTP 输入、新用户注册以及其他与登录相关的类似屏幕。

    帐户主题

    用户用于管理其帐户的控制台。

    管理控制台主题

    Keycloak 管理控制台的皮肤。

    电子邮件主题

    每当 Keycloak 必须发送电子邮件时,它都会使用此主题中定义的模板来制作电子邮件。

附加资源

启用国际化

Keycloak 中的每个 UI 屏幕都已国际化。默认语言为英语,但您可以选择要支持的语言环境以及默认语言环境。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击“本地化”选项卡。

  3. 启用“国际化”。

  4. 选择您将支持的语言。

    本地化选项卡

    Localization tab

    用户下次登录时,可以在登录页面上选择一种语言,用于登录屏幕、帐户控制台和管理控制台。

附加资源
  • 《服务器开发人员指南》解释了如何提供其他语言。主题提供的所有国际化文本都可以被“本地化”选项卡上的 realm 特定文本覆盖。

用户语言环境选择

语言环境选择器提供程序根据可用信息建议最佳语言环境。但是,通常不知道用户是谁。因此,先前经过身份验证的用户的语言环境会保存在持久性 Cookie 中。

选择语言环境的逻辑使用以下可用的第一个选项

  • 用户选择 - 当用户使用下拉语言环境选择器选择了一个语言环境时

  • 用户配置文件 - 当存在经过身份验证的用户并且用户设置了首选语言环境时

  • 客户端选择 - 由客户端传递,例如使用 ui_locales 参数

  • Cookie - 浏览器上最后选择的语言环境

  • 接受的语言 - 来自 Accept-Language 标头的语言环境

  • Realm 默认

  • 如果以上都不是,则回退到英语

当用户通过身份验证时,会触发一个操作来更新前面提到的持久 cookie 中的语言环境。如果用户在登录页面上通过语言环境选择器主动切换了语言环境,则用户的语言环境也会在此处更新。

如果您想更改选择语言环境的逻辑,您可以选择创建自定义的 LocaleSelectorProvider。有关详细信息,请参阅 服务器开发指南

控制登录选项

Keycloak 包含多个内置登录页面功能。

启用忘记密码

如果您启用 忘记密码,用户可以在忘记密码或丢失 OTP 生成器时重置其登录凭据。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 点击 登录 选项卡。

    登录选项卡

    Login Tab

  3. 忘记密码 切换为 开启

    忘记密码?链接将显示在您的登录页面中。

    忘记密码链接

    Forgot Password Link

  4. 电子邮件 选项卡中指定 主机发件人,以便 Keycloak 能够发送重置电子邮件。

  5. 点击此链接将用户带到他们可以输入用户名或电子邮件地址的地方,并收到一封包含重置凭据链接的电子邮件。

    忘记密码页面

    Forgot Password Page

电子邮件中发送的文本是可配置的。有关更多信息,请参阅 服务器开发指南

当用户点击电子邮件链接时,Keycloak 会要求他们更新密码;如果他们设置了 OTP 生成器,Keycloak 会要求他们重新配置 OTP 生成器。出于安全原因,该流程强制联合用户在重置凭据后重新登录,如果使用相同的身份验证会话(同一浏览器),则内部数据库用户保持登录状态。根据您组织的安全要求,您可以更改默认行为。

要更改此行为,请执行以下步骤

步骤
  1. 点击菜单中的 身份验证

  2. 点击 流程 选项卡。

  3. 选择 重置凭据 流程。

    重置凭据流程

    Reset Credentials Flow

    如果您不想重置 OTP,请将 重置 - 条件 OTP 子流程要求设置为 禁用

    发送重置电子邮件配置

    Send Reset Email Configuration

    如果您想更改强制登录选项的默认行为,请点击流程中的 发送重置电子邮件 设置图标,定义一个 别名,并为您选择最佳的 重置后强制登录 选项(true,始终强制重新身份验证,false,如果使用相同的浏览器,则保持用户登录状态,only-federated,默认值,仅强制联合用户再次登录)。

  4. 点击菜单中的 身份验证

  5. 点击 必需操作 选项卡。

  6. 确保 更新密码 已启用。

    必需操作

    Required Actions

启用记住我

已登录用户关闭浏览器会销毁他们的会话,该用户必须重新登录。您可以设置 Keycloak 以保持用户的登录会话打开,如果该用户在登录时点击了记住我复选框。此操作将登录 cookie 从仅会话 cookie 转换为持久 cookie。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 点击 登录 选项卡。

  3. 记住我 开关切换为 开启

    登录选项卡

    Login Tab Remember Me

    当您保存此设置时,记住我复选框将显示在 realm 的登录页面上。

    记住我

    Remember Me

ACR 到身份验证级别 (LoA) 映射

在 realm 的常规设置中,您可以定义哪个 身份验证上下文类引用 (ACR) 值映射到哪个 身份验证级别 (LoA)。ACR 可以是任何值,而 LoA 必须是数字。acr 声明可以在 OIDC 请求中发送的 claimsacr_values 参数中请求,并且它也包含在访问令牌和 ID 令牌中。映射的数字用于身份验证流程条件中。

如果特定客户端需要使用与 realm 不同的值,则也可以在客户端级别指定映射。但是,最佳实践是坚持 realm 映射。

ACR to LoA mapping

有关更多详细信息,请参阅 逐步验证官方 OIDC 规范

更新电子邮件工作流程 (UpdateEmail)

使用此工作流程,用户将必须使用 UPDATE_EMAIL 操作来更改自己的电子邮件地址。

此操作与单个电子邮件输入表单关联。如果 realm 禁用了电子邮件验证,则此操作将允许在不进行验证的情况下更新电子邮件。如果 realm 启用了电子邮件验证,则此操作将向新电子邮件地址发送电子邮件更新操作令牌,而无需更改帐户电子邮件。只有操作令牌触发才会完成电子邮件更新。

应用程序可以通过利用 UPDATE_EMAIL 作为 AIA(应用程序启动的操作) 将其用户发送到电子邮件更新表单。

UpdateEmail 是 预览版,尚未完全支持。此功能默认情况下处于禁用状态。

要启用,请使用 --features=preview--features=update-email 启动服务器

如果您启用此功能并且正在从以前的版本迁移,请在您的 realm 中启用 更新电子邮件 必需操作。否则,用户将无法更新其电子邮件地址。

配置 realm 密钥

Keycloak 使用的身份验证协议需要加密签名,有时还需要加密。Keycloak 使用非对称密钥对(私钥和公钥)来实现这一点。

Keycloak 一次只有一个活动密钥对,但也可以有多个被动密钥。活动密钥对用于创建新签名,而被动密钥对可用于验证以前的签名。这使得定期轮换密钥成为可能,而不会对用户造成任何停机或中断。

创建 realm 时,会自动生成密钥对和自签名证书。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 点击 密钥

  3. 从过滤器下拉列表中选择 被动密钥 以查看被动密钥。

  4. 从过滤器下拉列表中选择 禁用密钥 以查看禁用密钥。

密钥对可能具有 活动 状态,但仍未被选为 realm 当前的活动密钥对。用于签名的选定活动密钥对是根据优先级排序的第一个能够提供活动密钥对的密钥提供程序来选择的。

轮换密钥

我们建议您定期轮换密钥。首先创建优先级高于现有活动密钥的新密钥。您可以改为创建优先级相同的新密钥,并将之前的密钥设为被动密钥。

一旦新密钥可用,所有新令牌和 cookie 都将使用新密钥签名。当用户向应用程序进行身份验证时,SSO cookie 将使用新签名进行更新。当 OpenID Connect 令牌刷新时,新令牌将使用新密钥签名。最终,所有 cookie 和令牌都使用新密钥,一段时间后可以删除旧密钥。

删除旧密钥的频率是在安全性和确保所有 cookie 和令牌都更新之间进行权衡。考虑每三到六个月创建新密钥,并在创建新密钥后一到两个月删除旧密钥。如果用户在新密钥添加和旧密钥删除之间的时间段内处于非活动状态,则该用户将必须重新进行身份验证。

轮换密钥也适用于离线令牌。为了确保它们被更新,应用程序需要在旧密钥被删除之前刷新令牌。

添加生成的密钥对

使用此过程生成密钥对,包括自签名证书。

步骤
  1. 在管理控制台中选择 realm。

  2. 在菜单中单击“Realm 设置”。

  3. 点击 密钥 选项卡。

  4. 点击 提供程序 选项卡。

  5. 点击 添加提供程序 并选择 rsa-generated

  6. 优先级 字段中输入一个数字。此数字决定新密钥对是否成为活动密钥对。数字越大,密钥对越活跃。

  7. AES 密钥大小 选择一个值。

  8. 点击 保存

更改提供程序的优先级不会导致密钥重新生成,但如果您想更改密钥大小,您可以编辑提供程序,然后将生成新密钥。

通过提取证书轮换密钥

您可以通过从 RSA 生成的密钥对中提取证书,并在新的密钥库中使用该证书来轮换密钥。

先决条件
  • 生成的密钥对

步骤
  1. 在管理控制台中选择 realm。

  2. 点击 Realm 设置

  3. 点击 密钥 选项卡。

    将显示 活动 密钥列表。

  4. 在带有 RSA 密钥的行上,点击 公钥 下的 证书

    证书以文本形式显示。

  5. 将证书保存到文件,并将其括在以下行中。

    ----Begin Certificate----
    <Output>
    ----End Certificate----
  6. 使用 keytool 命令将密钥文件转换为 PEM 格式。

  7. 从密钥库中删除当前的 RSA 公钥证书。

    keytool -delete -keystore <keystore>.jks -storepass <password> -alias <key>
  8. 将新证书导入到密钥库中

    keytool -importcert -file domain.crt -keystore <keystore>.jks -storepass <password>  -alias <key>
  9. 重新构建应用程序。

    mvn clean install wildfly:deploy

添加现有密钥对和证书

要添加从其他地方获得的密钥对和证书,请选择 提供程序 并从下拉列表中选择 rsa。您可以更改优先级以确保新密钥对成为活动密钥对。

先决条件
  • 私钥文件。该文件必须是 PEM 格式。

步骤
  1. 在管理控制台中选择 realm。

  2. 点击 Realm 设置

  3. 点击 密钥 选项卡。

  4. 点击 提供程序 选项卡。

  5. 点击 添加提供程序 并选择 rsa

  6. 优先级 字段中输入一个数字。此数字决定新密钥对是否成为活动密钥对。

  7. 点击 浏览…​ 旁边的 私有 RSA 密钥 以上传私钥文件。

  8. 如果您有私钥的签名证书,请点击 浏览…​ 旁边的 X509 证书 以上传证书文件。如果您不上传证书,Keycloak 会自动生成自签名证书。

  9. 点击 保存

从 Java 密钥库加载密钥

要添加存储在主机上的 Java 密钥库文件中的密钥对和证书,请选择 提供程序 并从下拉列表中选择 java-keystore。您可以更改优先级以确保新密钥对成为活动密钥对。

为了加载关联的证书链,必须使用用于加载密钥对的相同 密钥别名 将其导入到 Java 密钥库文件中。

步骤
  1. 在管理控制台中选择 realm。

  2. 在菜单中单击“Realm 设置”。

  3. 点击 密钥 选项卡。

  4. 点击 提供程序 选项卡。

  5. 点击 添加提供程序 并选择 java-keystore

  6. 优先级 字段中输入一个数字。此数字决定新密钥对是否成为活动密钥对。

  7. 输入所需的 算法。请注意,该算法应与密钥类型匹配(例如,RS256 需要 RSA 私钥,ES256 需要 EC 私钥,AES 需要 AES 密钥)。

  8. 输入 密钥库 的值。密钥库文件的路径。

  9. 输入密钥库密码。此选项可以引用来自外部密钥库的值。

  10. 输入密钥库类型的值(JKSPKCS12BCFKS)。

  11. 输入要从密钥库加载的密钥别名的值。

  12. 输入密钥密码。此选项可以引用来自外部密钥库的值。

  13. 输入密钥用途的值(sig 用于签名,或 enc 用于加密)。请注意,用途应与算法类型匹配(例如,RS256sig,但 RSA-OAEPenc)。

  14. 点击 保存

并非所有密钥库类型都支持所有类型的密钥。例如,所有模式下的 JKS 和 fips 模式下的 PKCS12BCFIPS 提供程序)都不能存储密钥条目。

使密钥被动

步骤
  1. 在管理控制台中选择 realm。

  2. 在菜单中单击“Realm 设置”。

  3. 点击 密钥 选项卡。

  4. 点击 提供程序 选项卡。

  5. 单击要使其被动的密钥的提供程序。

  6. 活动切换为关闭

  7. 点击 保存

禁用密钥

步骤
  1. 在管理控制台中选择 realm。

  2. 在菜单中单击“Realm 设置”。

  3. 点击 密钥 选项卡。

  4. 点击 提供程序 选项卡。

  5. 单击要使其被动的密钥的提供程序。

  6. 已启用切换为关闭

  7. 点击 保存

泄露的密钥

Keycloak 将签名密钥仅本地存储,并且永远不会与客户端应用程序、用户或其他实体共享。但是,如果您认为您的 realm 签名密钥已泄露,您应首先生成新的密钥对(如上所述),然后立即删除泄露的密钥对。

或者,您可以从 Providers 表中删除提供程序。

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 单击 security-admin-console

  3. 向下滚动到 Access settings(访问设置)部分。

  4. 填写 Admin URL(管理 URL)字段。

  5. 单击 Advanced(高级)选项卡。

  6. Revocation(吊销)部分中,单击 Set to now(设置为现在)。

  7. 单击 Push(推送)。

推送 not-before 策略可确保客户端应用程序不接受由泄露的密钥签名的现有令牌。客户端应用程序也被迫从 Keycloak 下载新的密钥对,因此由泄露的密钥签名的令牌将无效。

REST 和保密客户端必须设置 Admin URL,以便 Keycloak 可以向客户端发送推送的 not-before 策略请求。

使用外部存储

组织可能拥有包含信息、密码和其他凭据的数据库。通常,您无法将现有数据存储迁移到 Keycloak 部署,因此 Keycloak 可以联合现有外部用户数据库。Keycloak 支持 LDAP 和 Active Directory,但您也可以通过使用 Keycloak User Storage SPI 为任何自定义用户数据库编写扩展。

当用户尝试登录时,Keycloak 会检查该用户的存储以查找该用户。如果 Keycloak 未找到该用户,Keycloak 会迭代 realm 的每个用户存储提供程序,直到找到匹配项。然后,来自外部数据存储的数据会映射到 Keycloak 运行时使用的标准用户模型中。然后,此用户模型会映射到 OIDC 令牌声明和 SAML 断言属性。

外部用户数据库很少具有支持 Keycloak 所有功能所需的数据,因此用户存储提供程序可以选择在 Keycloak 用户数据存储中本地存储项目。提供程序可以本地导入用户并定期与外部数据存储同步。此方法取决于提供程序的功能和提供程序的配置。例如,您的外部用户数据存储可能不支持 OTP。OTP 可以由 Keycloak 处理和存储,具体取决于提供程序。

添加提供程序

要添加存储提供程序,请执行以下步骤

步骤
  1. 单击菜单中的 User Federation(用户联合)。

    用户联合

    User federation

  2. 选择添加 KerberosLDAP 提供程序

    Keycloak 将您带到该提供程序的配置页面。

处理提供程序故障

如果用户存储提供程序失败,您可能无法登录和查看管理控制台中的用户。当使用存储提供程序查找用户时,Keycloak 不会检测到故障,因此它会取消调用。如果您有一个高优先级的存储提供程序在用户查找期间失败,则登录或用户查询将因异常而失败,并且不会故障转移到下一个配置的提供程序。

Keycloak 首先搜索本地 Keycloak 用户数据库以解析用户,然后再搜索任何 LDAP 或自定义用户存储提供程序。考虑在本地 Keycloak 用户数据库中创建一个管理员帐户,以防连接到您的 LDAP 和后端时出现问题。

每个 LDAP 和自定义用户存储提供程序在其管理控制台页面上都有一个 enable(启用)切换开关。禁用用户存储提供程序会在执行查询时跳过该提供程序,因此您可以使用较低优先级的不同提供程序中的用户帐户查看和登录。如果您的提供程序使用 import(导入)策略并且已禁用,则导入的用户仍然可以只读模式进行查找。

当存储提供程序查找失败时,Keycloak 不会进行故障转移,因为用户数据库通常在它们之间具有重复的用户名或重复的电子邮件。重复的用户名和电子邮件可能会导致问题,因为当管理员希望用户从另一个数据存储加载时,用户却从一个外部数据存储加载。

轻型目录访问协议 (LDAP) 和 Active Directory

Keycloak 包含 LDAP/AD 提供程序。您可以在一个 Keycloak realm 中联合多个不同的 LDAP 服务器,并将 LDAP 用户属性映射到 Keycloak 通用用户模型中。

默认情况下,Keycloak 映射用户名、电子邮件、名字和姓氏,但您也可以配置其他映射器。Keycloak 的 LDAP/AD 提供程序支持使用 LDAP/AD 协议和存储、编辑和同步模式进行密码验证。

配置联合 LDAP 存储

步骤
  1. 单击菜单中的 User Federation(用户联合)。

    用户联合

    User federation

  2. 单击 Add LDAP providers(添加 LDAP 提供程序)。

    Keycloak 将您带到 LDAP 配置页面。

    添加 LDAP 提供程序

    User federation

存储模式

Keycloak 将用户从 LDAP 导入到本地 Keycloak 用户数据库。用户数据库的此副本按需或通过定期后台任务同步。密码同步存在例外。Keycloak 永远不会导入密码。密码验证始终在 LDAP 服务器上进行。

同步的优势在于,所有 Keycloak 功能都可以高效工作,因为任何所需的额外每用户数据都本地存储。缺点是每次 Keycloak 首次查询特定用户时,Keycloak 都会执行相应的数据库插入。此外,当导入的用户作为搜索操作的一部分返回时,将为每个用户执行相应的 LDAP 搜索,以检查用户是否仍然存在于 LDAP 中并进行一些基本验证。

您可以将导入与 LDAP 服务器同步。当 LDAP 映射器始终从 LDAP 而不是数据库读取特定属性时,导入同步是不必要的。

您可以将 LDAP 与 Keycloak 一起使用,而无需将用户导入到 Keycloak 用户数据库中。LDAP 服务器备份 Keycloak 运行时使用的通用用户模型。如果 LDAP 不支持 Keycloak 功能所需的数据,则该功能将无法工作。这种方法的优点是您没有导入和同步 LDAP 用户副本到 Keycloak 用户数据库的资源消耗。

LDAP 配置页面上的 Import Users(导入用户)开关控制此存储模式。要导入用户,请将此开关切换为 ON(开启)。

如果您禁用 Import Users(导入用户),则无法将用户配置文件属性保存到 Keycloak 数据库中。此外,除了映射到 LDAP 的用户配置文件元数据外,您也无法保存元数据。此元数据可以包括角色映射、组映射和其他基于 LDAP 映射器配置的元数据。

当您尝试更改非 LDAP 映射的用户数据时,用户更新是不可能的。例如,您无法禁用 LDAP 映射的用户,除非用户的 enabled(已启用)标志映射到 LDAP 属性。

当处理导入的用户时,当查询用户以验证用户并对其进行修饰以使配置的映射器正常工作时,Keycloak 会执行 LDAP 搜索。这意味着在执行可能获取大量用户的未过滤用户搜索时必须格外小心,因为将为找到的每个导入用户发出 LDAP 搜索,这可能会对性能产生负面影响。

获取单个用户(例如在登录期间)的操作通常会被缓存,并且不应受到首次获取用户时执行的额外 LDAP 搜索的影响。

编辑模式

用户和管理员可以修改用户元数据,用户通过帐户控制台,管理员通过管理控制台。LDAP 配置页面上的 Edit Mode(编辑模式)配置定义了用户的 LDAP 更新权限。

READONLY(只读)

您无法更改用户名、电子邮件、名字、姓氏和其他映射的属性。每当用户尝试更新这些字段时,Keycloak 都会显示错误。不支持密码更新。

WRITABLE(可写)

您可以更改用户名、电子邮件、名字、姓氏和其他映射的属性和密码,并将它们自动与 LDAP 存储同步。

UNSYNCED(未同步)

Keycloak 将对用户名、电子邮件、名字、姓氏和密码的更改存储在 Keycloak 本地存储中,因此管理员必须将此数据同步回 LDAP。在此模式下,Keycloak 部署可以更新只读 LDAP 服务器上的用户元数据。当从 LDAP 导入用户到本地 Keycloak 用户数据库时,此选项也适用。

当 Keycloak 创建 LDAP 提供程序时,Keycloak 还会创建一组初始LDAP 映射器。Keycloak 根据 Vendor(供应商)、Edit Mode(编辑模式)和 Import Users(导入用户)开关的组合来配置这些映射器。例如,当编辑模式为 UNSYNCED(未同步)时,Keycloak 配置映射器以从数据库而不是 LDAP 服务器读取特定用户属性。但是,如果您稍后更改编辑模式,映射器的配置不会更改,因为无法检测到配置更改是否在 UNSYNCED(未同步)模式下更改。在创建 LDAP 提供程序时决定 Edit Mode(编辑模式)。此说明也适用于 Import Users(导入用户)开关。

其他配置选项

Console Display Name(控制台显示名称)

要在管理控制台中显示的提供程序的名称。

Priority(优先级)

查找用户或添加用户时提供程序的优先级。

Sync Registrations(同步注册)

如果您希望将 Keycloak 创建的新用户添加到 LDAP,请将此开关切换为 ON(开启)。

Allow Kerberos authentication(允许 Kerberos 身份验证)

在 realm 中启用 Kerberos/SPNEGO 身份验证,用户数据从 LDAP 提供。有关更多信息,请参阅Kerberos 部分

Remove invalid users during searches(在搜索期间删除无效用户)

如果用户存储中没有用户,则在执行搜索时从本地数据库中删除用户。如果为 true,则每当尝试查找用户时,将从本地数据库中删除不再从其相应的用户存储中可用的用户。如果为 false,则先前从用户存储导入的用户将保留在本地数据库中,作为只读和禁用状态,即使该用户不再从用户存储中可用。例如,用户直接从 LDAP 中删除,或者 Users DN 无效。请注意,此行为仅在用户尚未缓存时才会发生。

Relative User Creation DN(相对用户创建 DN)

新用户将在其中创建的 Users DN 的相对 DN。当使用 subtree(子树)搜索范围时,这允许在父 Users DN 的子 DN 中创建用户。例如,如果 Users DN 设置为 ou=people,dc=myorg,dc=com,并且 Relative User Creation DN 设置为 ou=engineering,则将从 Users DN 和所有子 DN 中获取用户,但新用户将存储在 ou=engineering,ou=people,dc=myorg,dc=com 中。换句话说,Keycloak 将 Relative User Creation DNUsers DN 连接(在连接 DN 时会自动添加逗号),并使用此结果 DN 来存储用户

组和角色映射器中也提供了类似的属性,允许将组和角色添加到用于搜索组/角色的基本 DN 的子 DN 中。

其他选项

将鼠标指针悬停在管理控制台中的工具提示上,以查看有关这些选项的更多详细信息。

通过 SSL 连接到 LDAP

当您为 LDAP 存储配置安全连接 URL(例如,ldaps://myhost.com:636)时,Keycloak 使用 SSL 与 LDAP 服务器通信。在 Keycloak 服务器端配置信任存储,以便 Keycloak 可以信任与 LDAP 的 SSL 连接 - 请参阅配置信任存储指南。

Use Truststore SPI 配置属性已弃用。通常应将其保留为 Always(始终)。

将 LDAP 用户同步到 Keycloak

如果您设置 Import Users(导入用户)选项,LDAP 提供程序将处理将 LDAP 用户导入到 Keycloak 本地数据库中。当用户首次登录或作为用户查询的一部分返回时(例如,使用管理控制台中的搜索字段),LDAP 提供程序会将 LDAP 用户导入到 Keycloak 数据库中。在身份验证期间,将验证 LDAP 密码。

如果您想将所有 LDAP 用户同步到 Keycloak 数据库中,请在 LDAP 提供程序配置页面上配置并启用 Sync Settings(同步设置)。

存在两种类型的同步

Periodic Full sync(定期完全同步)

此类型将所有 LDAP 用户同步到 Keycloak 数据库中。Keycloak 中已存在但在 LDAP 中不同的 LDAP 用户将直接在 Keycloak 数据库中更新。

定期更改的用户同步

同步时,Keycloak 仅创建或更新自上次同步后创建或更新的用户。

最佳同步方式是在首次创建 LDAP 提供程序时单击同步所有用户,然后设置定期同步更改的用户。

LDAP 映射器

LDAP 映射器是由 LDAP 提供程序触发的 listeners(监听器)。它们为 LDAP 集成提供了另一个扩展点。LDAP 映射器在以下情况下被触发:

  • 用户通过使用 LDAP 登录。

  • 用户首次注册。

  • 管理员控制台查询用户。

当您创建 LDAP 联合提供程序时,Keycloak 会自动为此提供程序提供一组 mappers(映射器)。用户可以更改此集合,用户还可以开发映射器或更新/删除现有映射器。

用户属性映射器

此映射器指定哪个 LDAP 属性映射到 Keycloak 用户的属性。例如,您可以将 mail LDAP 属性配置为 Keycloak 数据库中的 email 属性。对于此映射器实现,始终存在一对一映射。

全名映射器

此映射器指定用户的全名。Keycloak 将名称保存在 LDAP 属性(通常为 cn)中,并将该名称映射到 Keycloak 数据库中的 firstNamelastname 属性。对于 LDAP 部署,cn 包含用户的全名是很常见的。

当您在 Keycloak 中注册新用户且 LDAP 提供程序的 同步注册 设置为“开启”时,全名映射器允许回退到用户名。当使用 Microsoft Active Directory (MSAD) 时,此回退非常有用。MSAD 的常见设置是将 cn LDAP 属性配置为全名,同时在 LDAP 提供程序配置中使用 cn LDAP 属性作为 RDN LDAP 属性。通过此设置,Keycloak 会回退到用户名。例如,如果您创建 Keycloak 用户“john123”并将名字和姓氏留空,则全名映射器会将“john123”保存为 LDAP 中 cn 的值。当您稍后为名字和姓氏输入“John Doe”时,全名映射器会将 LDAP cn 更新为“John Doe”值,因为不再需要回退到用户名。

硬编码属性映射器

此映射器将硬编码的属性值添加到链接到 LDAP 的每个 Keycloak 用户。此映射器还可以强制设置 enabledemailVerified 用户属性的值。

角色映射器

此映射器配置从 LDAP 到 Keycloak 角色映射的角色映射。单个角色映射器可以将 LDAP 角色(通常是来自 LDAP 树特定分支的组)映射到与指定客户端的领域角色或客户端角色对应的角色。您可以为同一 LDAP 提供程序配置多个角色映射器。例如,您可以指定来自 ou=main,dc=example,dc=org 下组的角色映射映射到领域角色映射,而来自 ou=finance,dc=example,dc=org 下组的角色映射映射到客户端 finance 的客户端角色映射。

硬编码角色映射器

此映射器向来自 LDAP 提供程序的每个 Keycloak 用户授予指定的 Keycloak 角色。

组映射器

此映射器将 LDAP 树分支中的 LDAP 组映射到 Keycloak 中的组。此映射器还将用户组映射从 LDAP 传播到 Keycloak 中的用户组映射。

MSAD 用户帐户映射器

此映射器特定于 Microsoft Active Directory (MSAD)。它可以将 MSAD 用户帐户状态集成到 Keycloak 帐户状态中,例如启用帐户或密码过期。此映射器使用 userAccountControlpwdLastSet LDAP 属性,这些属性特定于 MSAD,而不是 LDAP 标准。例如,如果 pwdLastSet 的值为 0,则 Keycloak 用户必须更新其密码。结果是向用户添加了 UPDATE_PASSWORD 必需操作。如果 userAccountControl 的值为 514(禁用帐户),则 Keycloak 用户将被禁用。

证书映射器

此映射器映射 X.509 证书。Keycloak 将其与 X.509 身份验证和 PEM 格式的完整证书 作为身份源结合使用。此映射器的行为类似于 用户属性映射器,但 Keycloak 可以筛选存储 PEM 或 DER 格式证书的 LDAP 属性。使用此映射器启用 始终从 LDAP 读取值

用户属性映射器将基本的 Keycloak 用户属性(例如用户名、名字、姓氏和电子邮件)映射到相应的 LDAP 属性。您可以扩展这些映射器并提供您自己的其他属性映射。管理员控制台提供工具提示以帮助配置相应的映射器。

密码哈希

当 Keycloak 更新密码时,Keycloak 以纯文本格式发送密码。此操作与在内置 Keycloak 数据库中更新密码不同,在内置 Keycloak 数据库中,Keycloak 会在将密码发送到数据库之前对其进行哈希和加盐处理。对于 LDAP,Keycloak 依赖 LDAP 服务器来哈希和加盐密码。

默认情况下,MSAD、RHDS 或 FreeIPA 等 LDAP 服务器会哈希和加盐密码。OpenLDAP 或 ApacheDS 等其他 LDAP 服务器以纯文本形式存储密码,除非您使用 RFC3062 中描述的LDAPv3 密码修改扩展操作。在 LDAP 配置页面中启用 LDAPv3 密码修改扩展操作。有关更多详细信息,请参阅您的 LDAP 服务器的文档。

始终通过使用 ldapsearch 检查已更改的目录条目并 base64 解码 userPassword 属性值,来验证用户密码是否已正确哈希并且未以纯文本形式存储。

配置连接池

为了在管理 LDAP 连接时提高效率,并在处理多个连接时提高性能,您可以启用连接池。通过这样做,当连接关闭时,它将被返回到池中以供将来使用,从而减少始终创建新连接的成本。

LDAP 连接池配置使用以下系统属性进行配置

名称 描述

com.sun.jndi.ldap.connect.pool.authentication

可以池化的连接的空格分隔的身份验证类型列表。有效类型为“none”、“simple”和“DIGEST-MD5”

com.sun.jndi.ldap.connect.pool.initsize

表示整数的字符串表示形式,该整数表示在最初为身份创建连接时,每个连接身份要创建的连接数

com.sun.jndi.ldap.connect.pool.maxsize

表示整数的字符串表示形式,该整数表示每个连接身份可以同时维护的最大连接数

com.sun.jndi.ldap.connect.pool.prefsize

表示整数的字符串表示形式,该整数表示每个连接身份应同时维护的首选连接数

com.sun.jndi.ldap.connect.pool.timeout

表示整数的字符串表示形式,该整数表示空闲连接在池中可以保持多长时间(以毫秒为单位)而不会被关闭并从池中删除

com.sun.jndi.ldap.connect.pool.protocol

可以池化的连接的空格分隔的协议类型列表。有效类型为“plain”和“ssl”

com.sun.jndi.ldap.connect.pool.debug

指示要生成的调试输出级别的字符串。有效值为“fine”(跟踪连接创建和删除)和“all”(所有调试信息)

默认情况下,为 plainssl 协议都启用了连接池。

有关更多详细信息,请参阅 Java LDAP 连接池配置 文档。

要设置任何这些属性,您可以设置 JAVA_OPTS_APPEND 环境变量

export JAVA_OPTS_APPEND=-Dcom.sun.jndi.ldap.connect.pool.initsize=10 -Dcom.sun.jndi.ldap.connect.pool.maxsize=50

故障排除

对于类别 org.keycloak.storage.ldap,将日志记录级别提高到 TRACE 非常有用。通过此设置,许多日志消息将以 TRACE 级别发送到服务器日志,包括发送到 LDAP 服务器的所有查询以及用于发送查询的参数的日志记录。当您在用户论坛或 JIRA 上创建任何 LDAP 问题时,请考虑附加启用 TRACE 日志记录的服务器日志。如果日志太大,一个好的替代方法是仅包含来自服务器日志的代码片段,其中包含在导致您出现问题的操作期间添加到日志的消息。

  • 当您创建 LDAP 提供程序时,服务器日志中会出现一条 INFO 级别的消息,以以下内容开头

Creating new LDAP Store for the LDAP storage provider: ...

它显示了您的 LDAP 提供程序的配置。在您提出问题或报告错误之前,最好包含此消息以显示您的 LDAP 配置。最终可以随意替换您不想包含的某些配置更改为某些占位符值。一个示例是 bindDn=some-placeholder 。对于 connectionUrl,也可以随意替换它,但通常最好至少包含使用的协议(ldapldaps)。同样,包含您的 LDAP 映射器配置的详细信息也很有用,这些详细信息在 DEBUG 级别以如下消息显示

Mapper for provider: XXX, Mapper name: YYY, Provider: ZZZ ...

请注意,这些消息仅在启用 DEBUG 日志记录时显示。

  • 为了跟踪性能或连接池问题,请考虑将属性 com.sun.jndi.ldap.connect.pool.debug 的值设置为 all。此更改会在服务器日志中添加许多其他消息,其中包含 LDAP 连接池的日志记录。因此,您可以跟踪与连接池或性能相关的问题。有关更多详细信息,请参阅 配置连接池

更改连接池的配置后,您可能需要重新启动 Keycloak 服务器以强制重新初始化 LDAP 提供程序连接。

即使在服务器重新启动后,如果仍然没有出现有关连接池的消息,则可能表明连接池不适用于您的 LDAP 服务器。

  • 对于报告 LDAP 问题的情况,您可以考虑附加 LDAP 树的某些部分以及导致您环境中出现问题的目标数据。例如,如果某些用户的登录花费大量时间,您可以考虑附加他的 LDAP 条目,显示各种“组”条目的 member 属性的计数。在这种情况下,如果这些组条目映射到 Keycloak 中的某些组 LDAP 映射器(或角色 LDAP 映射器)等,则添加此信息可能很有用。

SSSD 和 FreeIPA 身份管理集成

Keycloak 包括 系统安全服务守护程序 (SSSD) 插件。SSSD 是 Fedora 和 Red Hat Enterprise Linux (RHEL) 的一部分,它提供对多个身份和身份验证提供程序的访问。SSSD 还提供诸如故障转移和离线支持等优势。有关更多信息,请参阅 Red Hat Enterprise Linux 身份管理文档

SSSD 与 FreeIPA 身份管理 (IdM) 服务器集成,提供身份验证和访问控制。通过此集成,Keycloak 可以针对特权访问管理 (PAM) 服务进行身份验证,并从 SSSD 检索用户数据。有关在 Linux 环境中使用 Red Hat Identity Management 的更多信息,请参阅 Red Hat Enterprise Linux 身份管理文档

keycloak sssd freeipa integration overview

Keycloak 和 SSSD 通过只读 D-Bus 接口进行通信。因此,配置和更新用户的方式是使用 FreeIPA/IdM 管理界面。默认情况下,该接口导入用户名、电子邮件、名字和姓氏。

Keycloak 自动注册组和角色,但不同步它们。组在首次访问用户时从 SSSD 导入,然后在 Keycloak 内部完全管理。管理员在 Keycloak 中进行的任何更改都不会与 SSSD 同步,反之亦然。

FreeIPA/IdM 服务器

FreeIPA 容器镜像Quay.io 上可用。要设置 FreeIPA 服务器,请参阅 FreeIPA 文档

步骤
  1. 使用以下命令运行您的 FreeIPA 服务器

     docker run --name freeipa-server-container -it \
     -h server.freeipa.local -e PASSWORD=YOUR_PASSWORD \
     -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
     -v /var/lib/ipa-data:/data:Z freeipa/freeipa-server

    带有 server.freeipa.local 的参数 -h 表示 FreeIPA/IdM 服务器主机名。将 YOUR_PASSWORD 更改为您自己的密码。

  2. 容器启动后,更改 /etc/hosts 文件以包含

    x.x.x.x     server.freeipa.local

    如果您不进行此更改,则必须设置 DNS 服务器。

  3. 使用以下命令将您的 Linux 服务器注册到 IPA 域中,以便 SSSD 联合提供程序在 Keycloak 上启动并运行

     ipa-client-install --mkhomedir -p admin -w password
  4. 在客户端上运行以下命令以验证安装是否正常工作

     kinit admin
  5. 输入您的密码。

  6. 使用以下命令将用户添加到 IPA 服务器

    $ ipa user-add <username> --first=<first name> --last=<surname> --email=<email address> --phone=<telephoneNumber> --street=<street> --city=<city> --state=<state> --postalcode=<postal code> --password
  7. 使用 kinit 强制设置用户的密码。

     kinit <username>
  8. 输入以下内容以恢复正常的 IPA 操作

    kdestroy -A
    kinit admin

SSSD 和 D-Bus

联合提供程序使用 D-BUS 从 SSSD 获取数据。它使用 PAM 验证数据。

步骤
  1. 安装 sssd-dbus RPM。

    $ sudo yum install sssd-dbus
  2. 运行以下配置脚本

    $ bin/federation-sssd-setup.sh

    该脚本也可以用作配置 SSSD 和 PAM 以用于 Keycloak 的指南。它对 /etc/sssd/sssd.conf 进行了以下更改

      [domain/your-hostname.local]
      ...
      ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber
      ...
      [sssd]
      services = nss, sudo, pam, ssh, ifp
      ...
      [ifp]
      allowed_uids = root, yourOSUsername
      user_attributes = +mail, +telephoneNumber, +givenname, +sn

    ifp 服务已添加到 SSSD,并配置为允许操作系统用户通过此接口查询 IPA 服务器。

    该脚本还创建了一个新的 PAM 服务 /etc/pam.d/keycloak,以通过 SSSD 验证用户身份

    auth    required   pam_sss.so
    account required   pam_sss.so
  3. 运行 dbus-send 以确保设置成功。

    dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe /org/freedesktop/sssd/infopipe org.freedesktop.sssd.infopipe.GetUserAttr string:<username> array:string:mail,givenname,sn,telephoneNumber
    
    dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe /org/freedesktop/sssd/infopipe org.freedesktop.sssd.infopipe.GetUserGroups string:<username>

    如果设置成功,则每个命令分别显示用户的属性和组。如果出现超时或错误,则在 Keycloak 上运行的联合提供程序无法检索任何数据。此错误通常发生在服务器未注册到 FreeIPA IdM 服务器,或者没有访问 SSSD 服务的权限时。

    如果您没有访问 SSSD 服务的权限,请确保运行 Keycloak 服务器的用户在 /etc/sssd/sssd.conf 文件中的以下部分中

    [ifp]
    allowed_uids = root, yourOSUsername

    并且在主机内部创建了 ipaapi 系统用户。此用户对于 ifp 服务是必需的。检查用户是否在系统中创建。

    grep ipaapi /etc/passwd
    ipaapi:x:992:988:IPA Framework User:/:/sbin/nologin

启用 SSSD 联合提供程序

Keycloak 使用 DBus-Java 项目与 D-Bus 进行低级别通信,并使用 JNA 通过操作系统可插拔身份验证模块 (PAM) 进行身份验证。

尽管现在 Keycloak 包含运行 SSSD 提供程序所需的所有库,但仍需要 JDK 版本 21。因此,只有在主机配置正确且使用 JDK 21 运行 Keycloak 时,才会显示 SSSD 提供程序。

配置联合 SSSD 存储

安装完成后,配置联合 SSSD 存储。

步骤
  1. 单击菜单中的 User Federation(用户联合)。

  2. 如果一切设置成功,页面上将显示添加 SSSD 提供程序按钮。点击它。

  3. 为新提供程序分配一个名称。

  4. 点击 保存

现在您可以使用 FreeIPA/IdM 用户和凭据对 Keycloak 进行身份验证。

自定义提供程序

Keycloak 确实有一个用户存储联合服务提供商接口 (SPI),用于开发自定义提供程序。您可以在服务器开发人员指南中找到有关开发客户提供程序的文档。

管理用户

在管理控制台中,您可以执行各种操作来管理用户。

创建用户

您在您打算拥有这些用户所需应用程序的 realm 中创建用户。 避免在 master realm 中创建用户,master realm 仅用于创建其他 realm。

前提条件
  • 您位于 master realm 以外的 realm 中。

步骤
  1. 在菜单中点击用户

  2. 点击添加用户

  3. 输入新用户的详细信息。

    用户名是唯一必填字段。
  4. 点击保存。 保存详细信息后,将显示新用户的管理页面。

管理用户属性

在 Keycloak 中,用户与一组属性相关联。 这些属性用于更好地描述和识别 Keycloak 中的用户,以及将有关他们的附加信息传递给应用程序。

用户配置文件定义了一个明确的模式,用于表示用户属性以及它们在 realm 中的管理方式。 通过提供用户信息的一致视图,它允许管理员控制属性管理方式的不同方面,并使扩展 Keycloak 以支持其他属性变得更加容易。

虽然用户配置文件主要针对最终用户可以管理的属性(例如:名字和姓氏、电话等),但它也用于管理您想要与用户关联的任何其他元数据。

除了其他功能外,用户配置文件还使管理员能够

  • 定义用户属性的模式

  • 根据上下文信息定义属性是否为必需(例如:如果仅对用户、管理员或两者都必需,或者取决于所请求的范围。)

  • 定义查看和编辑用户属性的特定权限,从而可以遵守严格的隐私要求,其中某些属性不能被第三方(包括管理员)查看或更改

  • 动态强制执行用户配置文件合规性,以便用户信息始终更新并符合与属性关联的元数据和规则

  • 通过利用内置验证器或编写自定义验证器,在每个属性的基础上定义验证规则

  • 根据属性定义,动态呈现用户在帐户控制台中与之交互的表单,例如注册、更新个人资料、代理和个人信息,而无需手动更改主题。

  • 自定义管理控制台中的用户管理界面,以便根据用户配置文件模式动态呈现属性

用户配置文件模式或配置使用 JSON 格式来表示属性及其元数据。 在管理控制台中,您可以通过点击左侧菜单中的Realm 设置,然后点击该页面上的用户配置文件选项卡来管理配置。

在接下来的章节中,我们将了解如何创建您自己的用户配置文件模式或配置,以及如何管理属性。

了解默认配置

默认情况下,Keycloak 提供了一个基本的用户配置文件配置,涵盖了一些最常见的用户属性

名称 描述

username

用户名

email

最终用户的首选电子邮件地址。

firstName

最终用户的给定名称或名字

lastName

最终用户的姓氏

在 Keycloak 中,“用户名”和“电子邮件”属性都经过特殊处理,因为它们通常用于识别、验证和链接用户帐户。 对于这些属性,您只能更改其设置,而不能删除它们。

“用户名”和“电子邮件”属性的行为会根据您 realm 的“登录”设置而变化。 例如,更改“将电子邮件作为用户名”或“编辑用户名”设置将覆盖您在用户配置文件配置中设置的任何配置。

正如您将在以下章节中看到的那样,您可以自由更改默认配置,方法是引入您自己的属性或更改任何可用属性的设置,以更好地满足您的需求。

了解用户配置文件上下文

在 Keycloak 中,用户通过不同的上下文进行管理

  • 注册

  • 更新个人资料

  • 通过代理或社交提供商进行身份验证时审查个人资料

  • 帐户控制台

  • 管理(例如:管理控制台和 Admin REST API)

除了“管理”上下文之外,所有其他上下文都被视为最终用户上下文,因为它们与用户自助服务流程相关。

了解这些上下文对于理解在管理用户时用户配置文件配置将在何处生效非常重要。 无论用户在哪个上下文中被管理,都将使用相同的用户配置文件配置来呈现 UI 并验证属性值。

正如您将在以下章节中看到的那样,您可能会限制某些属性仅在管理上下文中可用,并为最终用户完全禁用它们。 反之亦然,如果您不希望管理员访问某些用户属性,而只允许最终用户访问。

了解托管和非托管属性

默认情况下,Keycloak 只会识别在您的用户配置文件配置中定义的属性。 服务器会忽略任何其他未在此处明确定义的属性。

通过严格控制可以为用户设置哪些用户属性以及如何验证其值,Keycloak 可以为您的 realm 添加另一道防御屏障,并帮助您防止与用户关联的意外属性和值。

也就是说,用户属性可以按如下方式分类

  • 托管。 这些是受您的用户配置文件控制的属性,您希望允许最终用户和管理员从任何用户配置文件上下文中管理它们。 对于这些属性,您希望完全控制它们的管理方式和时间。

  • 非托管。 这些是您未在用户配置文件中明确定义的属性,因此默认情况下 Keycloak 会完全忽略它们。

虽然默认情况下禁用非托管属性,但您可以使用不同的策略配置您的 realm,以定义服务器如何处理它们。 为此,请点击左侧菜单中的Realm 设置,点击常规选项卡,然后从非托管属性设置中选择以下任何选项

  • 已禁用。 这是默认策略,因此非托管属性在所有用户配置文件上下文中都被禁用。

  • 已启用。 此策略在所有用户配置文件上下文中启用非托管属性。

  • 管理员可以查看。 此策略仅在管理上下文中以只读方式启用非托管属性。

  • 管理员可以编辑。 此策略仅在管理上下文中启用非托管属性以进行读取和写入。

这些策略使您可以精细地控制服务器将如何处理非托管属性。 您可以选择完全禁用,或者仅在通过管理上下文管理用户时支持非托管属性。

当启用非托管属性(即使是部分启用)时,您可以从管理控制台中的“用户详细信息”UI 的“属性”选项卡管理它们。 如果策略设置为“已禁用”,则此选项卡不可用。

作为安全建议,请尽量遵守最严格的策略(例如:“已禁用”或“管理员可以编辑”),以防止当用户通过最终用户上下文管理其个人资料时,为您的用户设置意外属性(和值)。 避免设置“已启用”策略,并优先在您的用户配置文件配置中定义最终用户可以管理的所有属性,并在您的控制之下。

“已启用”策略的目标是 realm 从以前版本的 Keycloak 迁移,并避免在使用自定义主题和使用他们自己的自定义用户属性扩展服务器时破坏行为。

正如您将在以下章节中看到的那样,您还可以通过选择属性是否应用户和/或管理员可见或可写来限制属性的受众。

对于非托管属性,最大长度为 2048 个字符。 要指定不同的最小或最大长度,请将非托管属性更改为托管属性并添加长度验证器。

Keycloak 在其内部缓存中缓存用户相关对象。 属性越长,缓存消耗的内存就越多。 因此,建议限制长度属性的大小。 考虑在 Keycloak 外部存储大型对象,并通过 ID 或 URL 引用它们。

管理用户配置文件

用户配置文件配置是在每个 realm 的基础上进行管理的。 为此,请点击左侧菜单中的Realm 设置链接,然后点击用户配置文件选项卡。

用户配置文件选项卡

user profile tab

属性子选项卡中,您可以看到所有托管属性的列表。

属性组子选项卡中,您可以管理属性组。 属性组允许您关联属性,以便在呈现面向用户的表单时将它们一起显示。

JSON 编辑器子选项卡中,您可以查看和编辑 JSON 配置。 您可以使用此选项卡来获取当前配置或手动管理它。 您在此选项卡上所做的任何更改都会反映在其他选项卡中,反之亦然。

在下一节中,您将学习如何管理属性。

管理属性

属性子选项卡中,您可以创建、编辑和删除托管属性。

要定义新属性并将其与用户配置文件关联,请点击属性列表顶部的创建属性按钮。

属性配置

user profile create attribute

配置属性时,您可以定义以下设置

名称

属性的名称,用于唯一标识属性。

显示名称

属性的用户友好名称,主要在呈现面向用户的表单时使用。 它还支持使用国际化消息

多值

如果启用,则属性支持多个值,并且 UI 会相应呈现以允许设置多个值。 启用此设置时,请确保添加验证器以设置值的硬性限制。

属性组

属性所属的属性组(如果有)。

启用条件

启用或禁用属性。 如果设置为始终,则该属性在任何用户配置文件上下文中都可用。 如果设置为请求作用域,则仅当代表用户的客户端请求一组或多个作用域时,该属性才可用。 您可以使用此选项根据请求的客户端作用域动态强制执行某些属性。 对于管理控制台,不评估作用域,并且始终启用该属性。 这是因为按作用域过滤属性仅在运行最终用户身份验证流程时才有效。

必需

设置将属性标记为必填的条件。如果禁用,则该属性是可选的。如果启用,您可以设置 Required for 设置,以根据用户配置文件上下文将属性标记为必填,以便该属性对于最终用户(通过最终用户上下文)或管理员(通过管理上下文)或两者都是必填的。您还可以设置 Required when 设置,以仅当请求了一组或多个客户端范围时才将属性标记为必填。如果设置为 Always,则该属性在任何用户配置文件上下文中都是必填的。如果设置为 Scopes are requested,则仅当代表用户操作的客户端请求一组或多个范围时,该属性才是必填的。对于帐户和管理控制台,不评估范围,并且该属性不是必填的。这是因为按范围过滤属性仅在运行身份验证流程时才有效。

权限

在本节中,您可以定义从最终用户或管理上下文中管理属性时的读取和写入权限。Who can edit 设置将属性标记为可由 User 和/或 Admin 从最终用户和管理上下文中分别写入。Who can view 设置将属性标记为可由 User 和/或 Admin 从最终用户和管理上下文中分别读取。

验证

在本节中,您可以定义在管理属性值时将执行的验证。Keycloak 提供了一组内置的验证器,您可以从中选择,并且可以添加您自己的验证器。有关更多详细信息,请参阅 验证属性 部分。

注解

在本节中,您可以将注解与属性关联。注解主要用于将额外的元数据传递到前端以进行渲染。有关更多详细信息,请参阅 定义 UI 注解 部分。

当您创建属性时,该属性仅在管理上下文中可用,以避免意外地向最终用户公开属性。实际上,当最终用户通过最终用户上下文管理他们的个人资料时,该属性将无法被最终用户访问。您可以随时根据您的需要更改 Permissions 设置。

验证属性

您可以启用对受管理属性的验证,以确保属性值符合特定规则。为此,您可以在管理属性时从 Validations 设置中添加或删除验证器。

属性验证

user profile validation

验证发生在任何写入属性的时候,并且它们可能会抛出错误,当值未能通过验证时,这些错误将显示在 UI 中。

出于安全原因,每个可由用户编辑的属性都应该进行验证,以限制用户输入的值的大小。如果未指定 length 验证器,Keycloak 默认最大长度为 2048 个字符。

内置验证器

Keycloak 提供了一些内置的验证器供您选择,您也可以通过扩展 Validator SPI 来提供您自己的验证器。

以下列表提供了所有内置验证器的列表

名称 描述 配置

length

检查字符串值的长度,基于最小和最大长度。

min:一个整数,用于定义允许的最小长度。

max:一个整数,用于定义允许的最大长度。

trim-disabled:一个布尔值,用于定义在验证之前是否修剪值。

integer

检查值是否为整数,并在下限和/或上限范围内。如果未定义范围,则验证器仅检查值是否为有效数字。

min:一个整数,用于定义下限范围。

max:一个整数,用于定义上限范围。

double

检查值是否为双精度浮点数,并在下限和/或上限范围内。如果未定义范围,则验证器仅检查值是否为有效数字。

min:一个整数,用于定义下限范围。

max:一个整数,用于定义上限范围。

uri

检查值是否为有效的 URI。

None

pattern

检查值是否与特定的 RegEx 模式匹配。

pattern:用于验证值的 RegEx 模式。

error-message:i18n 捆绑包中错误消息的键。如果未设置,则使用通用消息。

email

检查值是否具有有效的电子邮件格式。

max-local-length:一个整数,用于定义电子邮件本地部分的最大长度。根据规范,默认为 64。

local-date

检查值是否具有基于领域和/或用户区域设置的有效格式。

None

iso-date

检查值是否具有基于 ISO 8601 的有效格式。此验证器可以与使用 html5-date 输入类型的输入一起使用。

None

person-name-prohibited-characters

检查值是否为有效的人员姓名,作为防止脚本注入等攻击的额外屏障。验证基于默认的 RegEx 模式,该模式阻止人员姓名中不常见的字符。

error-message:i18n 捆绑包中错误消息的键。如果未设置,则使用通用消息。

username-prohibited-characters

检查值是否为有效的用户名,作为防止脚本注入等攻击的额外屏障。验证基于默认的 RegEx 模式,该模式阻止用户名中不常见的字符。当领域设置 Email as username 启用时,将跳过此验证器以允许电子邮件值。

error-message:i18n 捆绑包中错误消息的键。如果未设置,则使用通用消息。

options

检查值是否来自定义的允许值集合。用于验证通过选择和多选字段输入的值非常有用。

options:包含允许值的字符串数组。

up-username-not-idn-homograph

该字段只能包含拉丁字符和常见的 Unicode 字符。对于可能遭受 IDN 同形字攻击的字段(通常是用户名)很有用。

error-message:i18n 捆绑包中错误消息的键。如果未设置,则使用通用消息。

multivalued

验证多值属性的大小。

min:一个整数,用于定义允许的最小属性值计数。

max:一个整数,用于定义允许的最大属性值计数。

定义 UI 注解

为了将额外的信息传递给前端,可以使用注解来装饰属性,以指示如何渲染属性。当扩展 Keycloak 主题以基于与属性关联的注解动态渲染页面时,此功能主要有用。

注解用于例如 更改属性的 HTML type更改属性的 DOM 表示形式,正如您将在以下部分中看到的那样。

属性注解

user profile annotation

注解是与 UI 共享的键/值对,以便它们可以更改与属性对应的 HTML 元素的渲染方式。您可以为属性设置任何您想要的注解,只要注解受您的领域正在使用的主题支持。

您唯一的限制是避免在其键中使用 kc 前缀的注解,因为使用此前缀的注解是 Keycloak 保留的。

内置注解

以下注解受 Keycloak 内置主题支持

名称 描述

inputType

表单输入字段的类型。可用类型在下表中描述。

inputHelperTextBefore

在输入字段之前(上方)渲染的辅助文本。此处可以使用直接文本或国际化模式(如 ${i18n.key})。文本在渲染到页面中时不会进行 HTML 转义,因此您可以在此处使用 HTML 标签来格式化文本,但您也必须正确转义 HTML 控制字符。

inputHelperTextAfter

在输入字段之后(下方)渲染的辅助文本。此处可以使用直接文本或国际化模式(如 ${i18n.key})。文本在渲染到页面中时不会进行 HTML 转义,因此您可以在此处使用 HTML 标签来格式化文本,但您也必须正确转义 HTML 控制字符。

inputOptionsFromValidation

用于选择和多选类型的注解。用于从自定义属性验证中获取输入选项的可选名称。请参阅下方的 详细描述

inputOptionLabelsI18nPrefix

用于选择和多选类型的注解。用于在 UI 中渲染选项的国际化键前缀。请参阅下方的 详细描述

inputOptionLabels

用于选择和多选类型的注解。用于定义选项的 UI 标签的可选映射(直接或使用国际化)。请参阅下方的 详细描述

inputTypePlaceholder

应用于字段的 HTML 输入 placeholder 属性 - 指定一个简短的提示,描述输入字段的预期值(例如,示例值或预期格式的简短描述)。当用户输入值之前,简短的提示会显示在输入字段中。

inputTypeSize

应用于字段的 HTML 输入 size 属性 - 指定单行输入字段的宽度,以字符为单位。对于基于 HTML select 类型的字段,它指定显示的选项行数。可能无法工作,具体取决于所用主题中的 CSS!

inputTypeCols

应用于字段的 HTML 输入 cols 属性 - 指定 textarea 类型的宽度,以字符为单位。可能无法工作,具体取决于所用主题中的 CSS!

inputTypeRows

应用于字段的 HTML 输入 rows 属性 - 指定 textarea 类型的高度,以字符为单位。对于选择字段,它指定显示的选项行数。可能无法工作,具体取决于所用主题中的 CSS!

inputTypePattern

应用于字段的 HTML 输入 pattern 属性,提供客户端验证 - 指定一个正则表达式,用于检查输入字段的值。对于单行输入很有用。

inputTypeMaxLength

应用于字段的 HTML 输入 maxlength 属性,提供客户端验证 - 可以输入到输入字段中的文本的最大长度。对于文本字段很有用。

inputTypeMinLength

应用于字段的 HTML 输入 minlength 属性,提供客户端验证 - 可以输入到输入字段中的文本的最小长度。对于文本字段很有用。

inputTypeMax

应用于字段的 HTML 输入 max 属性,提供客户端验证 - 可以输入到输入字段中的最大值。对于数字字段很有用。

inputTypeMin

应用于字段的 HTML 输入 min 属性,提供客户端验证 - 可以输入到输入字段中的最小值。对于数字字段很有用。

inputTypeStep

应用于字段的 HTML 输入 step 属性 - 指定输入字段中合法数字之间的间隔。对于数字字段很有用。

数字格式

如果设置,data-kcNumberFormat 属性将添加到字段,以基于给定的格式格式化值。此注解针对的是数字,其中格式基于确定位置中预期位数的数量。例如,格式 ({2}) {5}-{4} 会将字段值格式化为 (00) 00000-0000

数字取消格式化

如果设置,data-kcNumberUnFormat 属性将添加到字段,以在提交表单之前基于给定的格式格式化值。如果您不想为特定属性存储任何格式,而只想在客户端格式化值,则此注解非常有用。例如,如果当前值为 (00) 00000-0000,如果您将值 {11} 或您想要的任何其他格式设置为此注解,通过指定一组或多组数字,则该值将更改为 00000000000。请确保添加验证器以在存储值之前执行服务器端验证。

字段类型使用 HTML 表单字段标签和应用于它们的属性 - 它们的行为基于 HTML 规范和浏览器对它们的支持。

视觉渲染也取决于所用主题中应用的 CSS 样式。

更改属性的 HTML type

您可以通过设置 inputType 注解来更改 HTML5 输入元素的 type。可用类型包括

名称 描述 使用的 HTML 标签

text

单行文本输入。

input

textarea

多行文本输入。

textarea

select

常见的单选输入。请参阅下方的 描述如何配置选项

select

select-radiobuttons

通过单选按钮组的单选输入。请参阅下方的 描述如何配置选项

输入组

multiselect

常见的多选输入。请参阅下方的 描述如何配置选项

select

multiselect-checkboxes

通过复选框组的多选输入。请参阅下方的 描述如何配置选项

输入组

html5-email

基于 HTML 5 规范的电子邮件地址的单行文本输入。

input

html5-tel

基于 HTML 5 规范的电话号码的单行文本输入。

input

html5-url

基于 HTML 5 规范的 URL 的单行文本输入。

input

html5-number

基于 HTML 5 规范的数字(整数或浮点数,取决于 step)的单行输入。

input

html5-range

基于 HTML 5 规范的用于输入数字的滑块。

input

html5-datetime-local

基于 HTML 5 规范的日期时间输入。

input

html5-date

基于 HTML 5 规范的日期输入。

input

html5-month

基于 HTML 5 规范的月份输入。

input

html5-week

基于 HTML 5 规范的星期输入。

input

html5-time

基于 HTML 5 规范的时间输入。

input

定义选择和多选字段的选项

选择和多选字段的选项取自应用于属性的验证,以确保 UI 中呈现的验证和字段选项始终一致。默认情况下,选项取自内置的 options 验证。

您可以使用多种方法为选择和多选选项提供良好的人类可读标签。最简单的情况是属性值与 UI 标签相同。在这种情况下,无需额外的配置。

选项值与 UI 标签相同

user profile select options simple

当属性值是某种不适用于 UI 的 ID 时,您可以使用 inputOptionLabelsI18nPrefix 注解提供的简单国际化支持。它定义了国际化键的前缀,选项值是附加到此前缀的点。

使用 i18n 键前缀的 UI 标签的简单国际化

user profile select options simple i18n

选项值的本地化 UI 标签文本必须通过 userprofile.jobtitle.swenguserprofile.jobtitle.swarch 键提供,然后使用通用的本地化机制。

您还可以使用 inputOptionLabels 注解为各个选项提供标签。它包含一个选项标签的映射 - 映射中的键是选项值(在验证中定义),映射中的值是 UI 标签文本本身或该选项的国际化模式(例如 ${i18n.key})。

您必须使用用户配置文件的 JSON 编辑器 来输入映射作为 inputOptionLabels 注解值。

直接输入的各个选项标签示例(不使用国际化)

"attributes": [
<...
{
  "name": "jobTitle",
  "validations": {
    "options": {
      "options":[
        "sweng",
        "swarch"
      ]
    }
  },
  "annotations": {
    "inputType": "select",
    "inputOptionLabels": {
      "sweng": "Software Engineer",
      "swarch": "Software Architect"
    }
  }
}
...
]

国际化的各个选项标签示例

"attributes": [
...
{
  "name": "jobTitle",
  "validations": {
    "options": {
      "options":[
        "sweng",
        "swarch"
      ]
    }
  },
  "annotations": {
    "inputType": "select-radiobuttons",
    "inputOptionLabels": {
      "sweng": "${jobtitle.swengineer}",
      "swarch": "${jobtitle.swarchitect}"
    }
  }
}
...
]

本地化文本必须通过 jobtitle.swengineerjobtitle.swarchitect 键提供,然后使用通用的本地化机制。

借助 inputOptionsFromValidation 属性注解,可以使用自定义验证器来提供选项。此验证必须具有提供选项数组的 options 配置。国际化的工作方式与内置 options 验证提供的选项相同。

由自定义验证器提供的选项

user profile select options custom validator

更改属性的 DOM 表示形式

您可以通过设置带有 kc 前缀的注解来启用额外的客户端行为。这些注解将转换为属性的相应元素中的 HTML 属性,并以 data- 为前缀。具有相同名称的脚本将被加载到动态页面,以便您可以根据自定义的 data- 属性从 DOM 中选择元素,并通过修改其 DOM 表示形式来相应地装饰它们。

例如,如果您向属性添加 kcMyCustomValidation 注解,则 HTML 属性 data-kcMyCustomValidation 将添加到属性的相应 HTML 元素中,并且 JavaScript 模块将从您的自定义主题中的 <THEME TYPE>/resources/js/kcMyCustomValidation.js 加载。有关如何将自定义 JavaScript 模块部署到主题的更多信息,请参阅 服务器开发人员指南

JavaScript 模块可以运行任何代码来自定义 DOM 和为每个属性呈现的元素。为此,您可以使用 userProfile.js 模块为您的自定义注解注册注解描述符,如下所示

import { registerElementAnnotatedBy } from "./userProfile.js";

registerElementAnnotatedBy({
  name: 'kcMyCustomValidation',
  onAdd(element) {
    var listener = function (event) {
        // do something on keyup
    };

    element.addEventListener("keyup", listener);

    // returns a cleanup function to remove the event listener
    return () => element.removeEventListener("keyup", listener);
  }
});

registerElementAnnotatedBy 是一种注册注解描述符的方法。描述符是一个对象,其中包含 name(引用注解名称)和一个 onAdd 函数。每当页面呈现或将带有注解的属性添加到 DOM 时,都会调用 onAdd 函数,以便您可以自定义元素的行为。

onAdd 函数还可以返回一个函数来执行清理操作。例如,如果您正在向元素添加事件侦听器,您可能希望在元素从 DOM 中移除时移除它们。

或者,如果 userProfile.js 不足以满足您的需求,您也可以使用任何您想要的 JavaScript 代码

document.querySelectorAll(`[data-kcMyCustomValidation]`).forEach((element) => {
    var listener = function (evt) {
        // do something on keyup
    };

    element.addEventListener("keyup", listener);
  });

管理属性组

属性组 子选项卡中,您可以创建、编辑和删除属性组。属性组允许您为相关的属性定义一个容器,以便它们在面向用户的表单中一起呈现。

属性组列表

user profile attribute group list

您无法删除绑定到属性的属性组。为此,您应该首先更新属性以删除绑定。

要创建新组,请单击属性组列表顶部的 创建属性组 按钮。

属性组配置

user profile create attribute group

配置组时,您可以定义以下设置

名称

属性的名称,用于唯一标识属性。

显示名称

属性的用户友好名称,主要在呈现面向用户的表单时使用。 它还支持使用国际化消息

显示描述

用户友好的文本,将在呈现面向用户的表单时显示为工具提示。它还支持 使用国际化消息

注解

在本节中,您可以将注解关联到属性。注解主要用于将额外的元数据传递到前端以进行呈现。

使用 JSON 配置

用户配置文件配置使用明确定义的 JSON 模式存储。您可以选择通过单击 JSON 编辑器 子选项卡直接编辑用户配置文件配置。

JSON 配置

user profile json config

JSON 模式定义如下

{
  "unmanagedAttributePolicy": "DISABLED",
  "attributes": [
    {
      "name": "myattribute",
      "multivalued": false,
      "displayName": "My Attribute",
      "group": "personalInfo",
      "required": {
        "roles": [ "user", "admin" ],
        "scopes": [ "foo", "bar" ]
      },
      "permissions": {
        "view": [ "admin", "user" ],
        "edit": [ "admin", "user" ]
      },
      "validations": {
        "email": {
          "max-local-length": 64
        },
        "length": {
          "max": 255
        }
      },
      "annotations": {
        "myannotation": "myannotation-value"
      }
    }
  ],
  "groups": [
    {
      "name": "personalInfo",
      "displayHeader": "Personal Information",
      "annotations": {
        "foo": ["foo-value"],
        "bar": ["bar-value"]
      }
    }
  ]
}

该模式支持您需要的任意数量的属性和组。

unmanagedAttributePolicy 属性通过设置以下值之一来定义非托管属性策略。有关更多详细信息,请查看 了解托管和非托管属性

  • 禁用

  • 启用

  • 管理员视图

  • 管理员编辑

属性模式

对于每个属性,您应该定义一个 name,以及可选的 requiredpermissionannotations 设置。

required 属性定义属性是否为必需。Keycloak 允许您根据不同的条件将属性设置为必需。

required 属性定义为空对象时,该属性始终为必需。

{
  "attributes": [
    {
      "name": "myattribute",
      "required": {}
  ]
}

另一方面,您可以选择仅对用户、管理员或两者都要求该属性为必需。以及仅在用户在 Keycloak 中进行身份验证时请求特定范围的情况下,将属性标记为必需。

要将属性标记为用户和/或管理员必需,请按如下所示设置 roles 属性

{
  "attributes": [
    {
      "name": "myattribute",
      "required": {
        "roles": ["user"]
      }
  ]
}

roles 属性需要一个数组,其值可以是 useradmin,具体取决于属性是用户还是管理员必需的。

同样,您可以选择在客户端在验证用户身份时请求一组或多个范围时,使属性成为必需。为此,您可以使用 scopes 属性,如下所示

{
  "attributes": [
    {
      "name": "myattribute",
      "required": {
        "scopes": ["foo"]
      }
  ]
}

scopes 属性是一个数组,其值可以是表示客户端范围的任何字符串。

属性级别的 permissions 属性可用于定义属性的读取和写入权限。权限的设置基于用户、管理员或两者是否可以对属性执行这些操作。

{
  "attributes": [
    {
      "name": "myattribute",
      "permissions": {
        "view": ["admin"],
        "edit": ["user"]
      }
  ]
}

viewedit 属性都期望一个数组,其值可以是 useradmin,具体取决于属性是否可由用户或管理员查看或编辑。

当授予 edit 权限时,将隐式授予 view 权限。

属性级别的 annotation 属性可用于将额外的元数据关联到属性。注解主要用于将有关属性的附加信息传递到前端,以便根据用户配置文件配置呈现用户属性。每个注解都是键/值对。

{
  "attributes": [
    {
      "name": "myattribute",
      "annotations": {
        "foo": ["foo-value"],
        "bar": ["bar-value"]
      }
  ]
}
属性组模式

对于每个属性组,您应该定义一个 name,以及可选的 annotations 设置。

属性级别的 annotation 属性可用于将额外的元数据关联到属性。注解主要用于将有关属性的附加信息传递到前端,以便根据用户配置文件配置呈现用户属性。每个注解都是键/值对。

自定义 UI 的呈现方式

来自所有用户配置文件上下文(包括管理控制台)的 UI 都会根据您的用户配置文件配置动态呈现。

默认呈现机制提供以下功能

  • 根据为属性设置的权限显示或隐藏字段。

  • 根据为属性设置的约束,为必填字段呈现标记。

  • 更改设置为属性的字段输入类型(文本、日期、数字、选择、多选)。

  • 根据为属性设置的权限将字段标记为只读。

  • 根据为属性设置的顺序对字段进行排序。

  • 对属于同一属性组的字段进行分组。

  • 动态地对属于同一属性组的字段进行分组。

排序属性

属性顺序通过在属性列表页面上拖放属性行来设置。

排序属性

user profile attribute list order

当字段在动态表单中呈现时,您在此页面中设置的顺序将得到遵守。

分组属性

当动态表单呈现时,它们将尝试将属于同一属性组的属性组合在一起。

动态更新配置文件表单

user profile update profile

当属性链接到属性组时,属性顺序也很重要,以确保同一组内的属性在同一组标题内紧密排列。否则,如果组内的属性没有顺序排列,您可能会在动态表单中多次呈现相同的组标题。

启用渐进式配置

为了确保最终用户配置文件符合配置,管理员可以使用 VerifyProfile 必需操作,以最终强制用户在向 Keycloak 验证身份时更新其配置文件。

VerifyProfile 操作类似于 UpdateProfile 操作。但是,它利用用户配置文件提供的所有功能来自动强制符合用户配置文件配置。

启用后,当用户进行身份验证时,VerifyProfile 操作将执行以下步骤

  • 检查用户配置文件是否完全符合为 realm 设置的用户配置文件配置。这意味着运行验证并确保所有验证都成功。

  • 如果不符合,则在身份验证期间执行一个额外的步骤,以便用户可以更新任何缺失或无效的属性。

  • 如果用户配置文件符合配置,则不执行任何额外的步骤,用户继续进行身份验证过程。

VerifyProfile 操作默认启用。要禁用它,请单击左侧菜单上的 身份验证 链接,然后单击 必需操作 选项卡。在此选项卡中,使用 VerifyProfile 操作的 已启用 开关来禁用它。

注册 VerifyProfile 必需操作

user profile register verify profile action

使用国际化消息

如果您想在配置属性、属性组和注解时使用国际化消息,您可以使用占位符设置它们的显示名称、描述和值,该占位符将转换为消息包中的消息。

为此,您可以使用占位符来解析消息键,例如 ${myAttributeName},其中 myAttributeName 是消息包中消息的键。有关如何将消息包添加到自定义主题的更多详细信息,请参阅 服务器开发人员指南

定义用户凭据

您可以在 凭据 选项卡中管理用户的凭据。

凭据管理

user credentials

您可以通过拖放行来更改凭据的优先级。新顺序决定了该用户凭据的优先级。最顶部的凭据具有最高的优先级。优先级决定了用户登录后首先显示哪个凭据。

类型

此列显示凭据的类型,例如 密码OTP

用户标签

这是一个可分配的标签,用于在登录期间作为选择选项呈现凭据时识别凭据。它可以设置为任何值来描述凭据。

数据

这是关于凭据的非机密技术信息。默认情况下它是隐藏的。您可以单击 显示数据…​ 以显示凭据的数据。

操作

单击 重置密码 以更改用户的密码,单击 删除 以删除凭据。

您无法在管理控制台中为特定用户配置其他类型的凭据;这项任务是用户的责任。

如果用户丢失了 OTP 设备或凭据已泄露,您可以删除用户的凭据。您只能在 凭据 选项卡中删除用户的凭据。

为用户设置密码

如果用户没有密码,或者密码已被删除,则会显示 设置密码 部分。

如果用户已经有密码,则可以在 重置密码 部分重置密码。

步骤
  1. 在菜单中单击 用户。将显示 用户 页面。

  2. 选择一个用户。

  3. 单击 凭据 选项卡。

  4. 设置密码 部分中键入新密码。

  5. 单击 设置密码

    如果 临时开启,则用户必须在首次登录时更改密码。要允许用户保留提供的密码,请将 临时 设置为 关闭。用户必须单击 设置密码 才能更改密码。

请求用户重置密码

您还可以请求用户重置密码。

步骤
  1. 在菜单中单击 用户。将显示 用户 页面。

  2. 选择一个用户。

  3. 单击 凭据 选项卡。

  4. 单击 凭据重置

  5. 从列表中选择 更新密码

  6. 单击 发送电子邮件。发送的电子邮件包含一个链接,该链接将用户定向到 更新密码 窗口。

  7. (可选)您可以设置电子邮件链接的有效期。这在 Realm 设置 中的 令牌 选项卡中设置为默认预设值。

创建 OTP

如果您的 realm 中 OTP 是有条件的,则用户必须导航到 Keycloak 帐户控制台以重新配置新的 OTP 生成器。如果 OTP 是必需的,则用户必须在登录时重新配置新的 OTP 生成器。

或者,您可以向用户发送电子邮件,请求用户重置 OTP 生成器。如果用户已经拥有 OTP 凭据,以下步骤也适用。

前提条件
  • 您已登录到相应的 realm。

步骤
  1. 在主菜单中单击 用户。将显示 用户 页面。

  2. 选择一个用户。

  3. 单击 凭据 选项卡。

  4. 单击 凭据重置

  5. 重置操作 设置为 配置 OTP

  6. 单击 发送电子邮件。发送的电子邮件包含一个链接,该链接将用户定向到 OTP 设置页面

允许用户自助注册

您可以将 Keycloak 用作第三方授权服务器来管理应用程序用户,包括自助注册的用户。如果您启用自助注册,登录页面将显示注册链接,以便用户可以创建帐户。

注册链接

registration link

用户必须在注册表单中添加个人资料信息才能完成注册。注册表单可以通过删除或添加用户必须填写的字段进行自定义。

关于身份代理和管理 API 的说明

即使禁用自助注册,仍然可以通过以下任一方式将新用户添加到 Keycloak:

  • 管理员可以使用管理控制台(或管理 REST API)添加新用户

  • 当启用身份代理时,通过身份提供商验证的新用户可能会自动添加/注册到 Keycloak 存储中。有关更多信息,请参阅身份代理章节中的首次登录流程部分

此外,来自第三方用户存储(例如 LDAP)的用户在启用特定用户存储时会自动在 Keycloak 中可用

附加资源

启用用户注册

启用用户自助注册。

步骤
  1. 在主菜单中点击 Realm 设置

  2. 点击 登录 选项卡。

  3. 用户注册 切换为 开启

启用此设置后,注册 链接将显示在管理控制台的登录页面上。

注册为新用户

作为新用户,您必须填写注册表单才能首次登录。您需要添加个人资料信息和密码才能注册。

注册表单

registration form

前提条件
  • 用户注册已启用。

步骤
  1. 点击登录页面上的 注册 链接。将显示注册页面。

  2. 输入用户个人资料信息。

  3. 输入新密码。

  4. 点击 注册

要求用户在注册时同意条款和条件

为了让用户注册,您可以要求其同意您的条款和条件。

需要同意条款和条件的注册表单

registration form with required tac

前提条件
  • 用户注册已启用。

  • 条款和条件必填操作已启用。

步骤
  1. 在菜单中点击 Authentication(认证)。点击 Flows(流程) 选项卡。

  2. 点击 registration(注册) 流程。

  3. Terms and Conditions(条款和条件) 行中选择 Required(必填)

    使条款和条件协议在注册时成为必需

    require tac agreement at registration

定义登录时需要的操作

您可以设置用户在首次登录时必须执行的操作。这些操作在用户提供凭据后是必需的。首次登录后,这些操作不再是必需的。您可以在该用户的 Details(详情) 选项卡上添加必需的操作。

即使管理员没有显式地将某些必需的操作添加到用户,这些操作也会在用户登录期间自动触发。例如,如果密码策略配置为用户密码需要每 X 天更改一次,则可以触发 Update password(更新密码) 操作。或者,如果某些用户属性不符合用户配置文件配置的要求,verify profile(验证个人资料) 操作可能会要求用户更新用户配置文件

以下是必需的操作类型的示例

更新密码

用户必须更改其密码。

配置 OTP

用户必须使用 Free OTP 或 Google Authenticator 应用程序在其移动设备上配置一次性密码生成器。

验证电子邮件

用户必须验证其电子邮件帐户。将向用户发送一封包含验证链接的电子邮件,用户必须点击该链接。成功完成此工作流程后,用户将被允许登录。

更新个人资料

用户必须更新个人资料信息,例如姓名、地址、电子邮件和电话号码。

某些操作直接添加到用户帐户是没有意义的。例如,Update User Locale(更新用户区域设置) 是一个辅助操作,用于处理一些本地化相关参数。另一个例子是 Delete Credential(删除凭据) 操作,它应该作为参数化 AIA 触发。关于这一点,如果管理员想要删除某些用户的凭据,管理员可以直接在管理控制台中执行此操作。Delete Credential(删除凭据) 操作专门用于例如Keycloak 帐户控制台

为一个用户设置必需的操作

您可以设置任何用户都需要的操作。

步骤
  1. 在菜单中点击用户

  2. 从列表中选择一个用户。

  3. 导航到 Required User Actions(必需的用户操作) 列表。

    user required action

  4. 选择要添加到帐户的所有操作。

  5. 点击操作名称旁边的 X 以移除它。

  6. 在选择要添加的操作后,点击 保存

为所有用户设置必需的操作

您可以指定所有新用户首次登录之前需要执行哪些操作。这些要求适用于通过 Users(用户) 页面上的 Add User(添加用户) 按钮或登录页面上的 Register(注册) 链接创建的用户。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 Required Actions(必需的操作) 选项卡。

  3. 为一个或多个必需的操作点击 Set as default action(设置为默认操作) 列中的复选框。当新用户首次登录时,必须执行所选的操作。

启用条款和条件作为必需的操作

您可以启用一个必需的操作,即新用户必须接受条款和条件才能首次登录 Keycloak。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 Required Actions(必需的操作) 选项卡。

  3. 启用 条款和条件 操作。

  4. 编辑基本登录主题中的 terms.ftl 文件。

附加资源

应用程序发起的动作

应用程序发起的动作 (AIA) 允许客户端应用程序请求用户在 Keycloak 端执行操作。通常,当 OIDC 客户端应用程序希望用户登录时,它会将用户重定向到登录 URL,如OIDC 章节中所述。登录后,用户将被重定向回客户端应用程序。用户执行管理员要求的操作,如上一节中所述,然后立即重定向回应用程序。但是,AIA 允许客户端应用程序在登录期间请求用户执行某些必需的操作。即使用户已在客户端上通过身份验证并且具有活动的 SSO 会话,也可以执行此操作。它通过将 kc_action 参数添加到 OIDC 登录 URL,其值包含请求的操作来触发。例如 kc_action=UPDATE_PASSWORD 参数。

用户可以取消应用程序发起的动作。在这种情况下,用户将被重定向回客户端应用程序。重定向 URI 将包含查询参数 kc_action_status=cancelledkc_action 以及已取消操作的名称。

kc_actionkc_action_status 参数是 Keycloak 专有的机制,OIDC 规范不支持。
应用程序发起的动作仅支持 OIDC 客户端。

因此,如果使用 AIA,示例流程类似于以下内容

  • 客户端应用程序将用户重定向到 OIDC 登录 URL,并带有附加参数,例如 kc_action=UPDATE_PASSWORD

  • 始终会触发身份验证流程部分中描述的 browser 流程。如果用户未通过身份验证,则该用户需要像正常登录期间一样进行身份验证。如果用户已经过身份验证,则可以通过 SSO cookie 自动重新身份验证,而无需主动重新身份验证并再次提供凭据。在这种情况下,该用户将直接重定向到具有特定操作的屏幕(在本例中为更新密码)。但是,在某些情况下,即使用户具有 SSO cookie,也需要主动重新身份验证(有关详细信息,请参阅下文)。

  • 具有特定操作(在本例中为 update password)的屏幕将显示给用户,以便用户需要执行特定操作

  • 然后用户被重定向回客户端应用程序

请注意,Keycloak 帐户控制台 使用 AIA 来请求更新密码或重置其他凭据,例如 OTP 或 WebAuthn。

即使使用了参数 kc_action,也不能认为用户总是执行该操作。例如,用户可能已手动从浏览器 URL 中删除了 kc_action 参数。因此,无法保证在客户端请求 kc_action=CONFIGURE_TOTP 后,用户帐户具有 OTP。如果您想验证用户是否配置了双因素身份验证器,则客户端应用程序可能需要检查它是否已配置。例如,通过检查令牌中的 acr 等声明。

AIA 期间的重新身份验证

如果用户由于活动的 SSO 会话而已通过身份验证,则该用户通常不需要主动重新身份验证。但是,如果该用户主动身份验证的时间超过五分钟前,则当请求某些 AIA 时,客户端仍然可以请求重新身份验证。以下是此指南的例外情况:

  • delete_account 操作将始终要求用户主动重新身份验证

  • UPDATE_PASSWORD 操作可能需要用户根据配置的最大身份验证年龄密码策略主动重新身份验证。如果未配置策略,也可以在配置特定必需操作时在必需的操作选项卡上配置策略。如果未在任何这些位置配置策略,则默认为五分钟。

  • 如果您想使用更短的重新身份验证,您仍然可以使用参数查询参数,例如 max_age 与指定的更短值,或者最终使用 prompt=login,这将始终要求用户主动重新身份验证,如 OIDC 规范中所述。请注意,不支持对 max_age 使用长于默认五分钟(或密码策略规定的值)的值。max_age 目前只能用于使该值短于默认的五分钟。

  • 如果启用了增强身份验证,且操作是添加或删除凭据,则需要使用与给定凭据级别对应的级别进行身份验证。如果用户已拥有特定级别的凭据,则存在此要求。例如,如果在身份验证流程中配置了 otpwebauthn 作为第二因素身份验证器(都在级别 2 的身份验证流程中),并且用户已拥有第二因素凭据(在本例中为 otpwebauthn),则用户需要使用现有的第二因素凭据进行身份验证,才能添加另一个第二级凭据。同样,删除现有的第二因素凭据(在本例中为 otpwebauthn)时,也需要使用现有的第二因素级别凭据进行身份验证。存在此要求是出于安全原因。

参数化 AIA

一些 AIA 可能需要与操作名称一起发送参数。例如,只有 AIA 才能触发 删除凭据 操作,并且它需要与操作名称一起发送参数,该参数指向要删除的凭据的 ID。因此,此示例的 URL 将是 kc_action=delete_credential:ce1008ac-f811-427f-825a-c0b878d1c24b。在这种情况下,冒号字符 (ce1008ac-f811-427f-825a-c0b878d1c24b) 后的部分包含要删除的特定用户的凭据 ID。删除凭据 操作会显示确认屏幕,用户可以在其中确认同意删除凭据。

Keycloak 账户控制台 通常在删除第二因素凭据时使用 删除凭据 操作。如果您想直接从自己的应用程序中使用此操作,可以查看账户控制台中的示例。但是,最好依赖账户控制台,而不是从您自己的应用程序管理凭据。

可用操作

要查看所有可用操作,请登录到管理控制台,然后转到右上角,单击 Realm infoProvider info 选项卡 → 找到提供程序 required-action。但请注意,根据在必需操作选项卡中为您的 realm 启用的操作,这可能会受到进一步限制。

搜索用户

搜索用户以查看有关用户的详细信息,例如用户的组和角色。

前提条件
  • 您位于用户所在的 realm 中。

步骤
  1. 在主菜单中单击 用户。将显示此 用户 页面。

  2. 在搜索框中键入您要搜索的用户的全名、姓氏、名字或电子邮件地址。搜索将返回所有符合您条件的用户。

    用于匹配用户的条件取决于搜索框中使用的语法

    1. "somevalue" → 执行字符串 "somevalue" 的精确搜索;

    2. *somevalue* → 执行中缀搜索,类似于 LIKE '%somevalue%' 数据库查询;

    3. somevalue*somevalue → 执行前缀搜索,类似于 LIKE 'somevalue%' 数据库查询。

步骤
  1. 在主菜单中单击 用户。将显示此 用户 页面。

  2. 单击 默认搜索 按钮,并将其切换到 属性搜索

  3. 单击 选择属性 按钮,并指定要搜索的属性。

  4. 选中 精确搜索 复选框以执行精确匹配,或保持未选中状态以对属性值使用中缀搜索。

  5. 单击 搜索 按钮以执行搜索。它将返回所有符合条件的用户。

用户 页面中执行的搜索涵盖 Keycloak 的数据库和配置的用户联合后端,例如 LDAP。在联合后端中找到的用户如果尚未存在于 Keycloak 的数据库中,将被导入到 Keycloak 的数据库中。

其他资源
  • 有关用户联合的更多信息,请参阅 用户联合

删除用户

您可以删除不再需要访问应用程序的用户。如果用户被删除,则用户个人资料和数据也将被删除。

步骤
  1. 在菜单中单击 用户。将显示 用户 页面。

  2. 单击 查看所有用户 以查找要删除的用户。

    或者,您可以使用搜索栏查找用户。
  3. 从要删除的用户旁边的操作菜单中单击 删除 并确认删除。

允许用户删除帐户

如果您在管理控制台中启用此功能,最终用户和应用程序可以在账户控制台中删除他们的帐户。启用此功能后,您可以将该功能授予特定用户。

启用删除帐户功能

您可以在 必需操作 选项卡上启用此功能。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 Required Actions(必需的操作) 选项卡。

  3. 删除帐户 行中选择 已启用

    必需操作选项卡上的删除帐户

    enable delete account action

授予用户 delete-account 角色

您可以向特定用户授予允许帐户删除的角色。

步骤
  1. 在菜单中点击用户

  2. 选择一个用户。

  3. 单击 角色映射 选项卡。

  4. 单击 分配角色 按钮。

  5. 单击 account delete-account

  6. 单击 分配

    Delete-account 角色

    delete-account role

删除您的帐户

一旦您拥有 delete-account 角色,您就可以删除自己的帐户。

  1. 登录到账户控制台。

  2. 个人信息 页面的底部,单击 删除帐户

    删除帐户页面

    Delete account page

  3. 输入您的凭据并确认删除。

    删除确认

    delete account confirm

    此操作不可逆。您在 Keycloak 中的所有数据都将被删除。

模拟用户

具有适当权限的管理员可以模拟用户。例如,如果用户在应用程序中遇到错误,管理员可以模拟用户来调查或重现该问题。

realm 中具有 impersonation 角色的任何用户都可以模拟用户。

步骤
  1. 在菜单中点击用户

  2. 单击要模拟的用户。

  3. 操作 列表中,选择 模拟

    user impersonate action

    • 如果管理员和用户在同一 realm 中,则管理员将被注销并自动以被模拟用户的身份登录。

    • 如果管理员和用户在不同的 realm 中,则管理员将保持登录状态,并且还将以该用户 realm 中用户的身份登录。

在这两种情况下,都会显示被模拟用户的 账户控制台

附加资源

启用 reCAPTCHA

为了保护注册免受机器人的侵害,Keycloak 集成了 Google reCAPTCHA(请参阅 设置 Google reCAPTCHA)和 reCAPTCHA Enterprise(请参阅 设置 Google reCAPTCHA Enterprise)。默认主题 (register.ftl) 支持 v2(可见、基于复选框)和 v3(基于分数、不可见)reCAPTCHA(请参阅 选择合适的 reCAPTCHA 密钥类型)。

设置 Google reCAPTCHA

  1. 在浏览器中输入以下 URL

    https://www.google.com/recaptcha/admin/create
  2. 创建 reCAPTCHA,并在 Challenge v2(可见复选框)或 Score-based v3(不可见)之间进行选择,以获取您的 reCAPTCHA 站点密钥和密钥。记下它们以供本过程将来使用。

    默认情况下不支持 localhost 域。如果您希望继续支持它们进行开发,您可以将它们添加到站点密钥的受支持域列表中。
  3. 导航到 Keycloak 管理控制台。

  4. 点击菜单中的 身份验证

  5. 点击 流程 选项卡。

  6. 从列表中选择 注册

  7. reCAPTCHA 要求设置为 必需。这将启用 reCAPTCHA。

  8. 单击 reCAPTCHA 行中的 齿轮图标 ⚙️。

    reCAPTCHA 配置

    recaptcha config

    1. 输入从 Google reCAPTCHA 网站生成的 reCAPTCHA 站点密钥

    2. 输入从 Google reCAPTCHA 网站生成的 reCAPTCHA 密钥

    3. 根据您的站点密钥类型切换 reCAPTCHA v3:对于基于分数的 reCAPTCHA (v3),切换为“开”;对于 challenge reCAPTCHA (v2),切换为“关”。

    4. (可选)切换 使用 recaptcha.net 以使用 www.recaptcha.net 而不是 www.google.com 域来获取 Cookie。有关更多信息,请参阅 reCAPTCHA 常见问题解答

  9. 授权 Google 将注册页面用作 iframe。

    在 Keycloak 中,网站不能在 iframe 中包含登录页面对话框。此限制是为了防止点击劫持攻击。您需要更改 Keycloak 中设置的默认 HTTP 响应标头。
    1. 在菜单中单击“Realm 设置”。

    2. 单击 安全防御 选项卡。

    3. X-Frame-Options 标头的字段中输入 https://www.google.com(如果您启用了 使用 recaptcha.net,则输入 https//www.recaptcha.net)。

    4. Content-Security-Policy 标头的字段中输入 https://www.google.com(如果您启用了 使用 recaptcha.net,则输入 https//www.recaptcha.net)。

设置 Google reCAPTCHA Enterprise

  1. 在浏览器中输入以下 URL

    https://developers.google.com/recaptcha/
  2. 为“网站”平台创建一个密钥,并选择所需的密钥类型。对于 v3 reCAPTCHA(不可见),保留默认设置,或者对于 v2 reCAPTCHA(可见),切换 使用复选框 challenge。记下站点密钥以供本过程将来使用。

    localhost 默认情况下有效。您不必指定域。
  3. 在您的 Google Cloud 项目中,转到 凭据 并创建一个 API 密钥。

    为了更好的安全性,单击 编辑 API 密钥 并添加 API 限制,以将密钥限制为仅 reCAPTCHA Enterprise API
  4. 导航到 Keycloak 管理控制台。

  5. 点击菜单中的 身份验证

  6. 点击 流程 选项卡。

  7. 复制“注册”流程。

  8. 将新流程绑定到 注册流程

  9. 编辑新流程

    1. 删除 reCAPTCHA 步骤。

    2. 将步骤 reCAPTCHA Enterprise 添加为“注册表单”(流程的第一步)的子步骤。

  10. reCAPTCHA Enterprise 要求设置为 必需

  11. 单击 reCAPTCHA Enterprise 行中的 齿轮图标 ⚙️。

    reCAPTCHA Enterprise 配置

    recaptcha enterprise config

    1. 输入您的 Google Cloud 控制台项目的 Recaptcha 项目 ID

    2. 输入在本过程开始时生成的 Recaptcha 站点密钥

    3. 输入在本过程开始时生成的 Recaptcha API 密钥

    4. 根据您的站点密钥类型切换 reCAPTCHA v3:对于基于分数的 reCAPTCHA (v3),切换为“开”;对于 challenge reCAPTCHA (v2),切换为“关”。

    5. (可选)根据您的需要自定义 最低分数阈值。将其设置为用户在 reCAPTCHA 上应达到的最低分数(介于 0.0 和 1.0 之间)才能被允许注册。请参阅 解释分数

    6. (可选)切换 使用 recaptcha.net 以使用 www.recaptcha.net 而不是 www.google.com 域来获取 Cookie。有关更多信息,请参阅 reCAPTCHA 常见问题解答

  12. 授权 Google 将注册页面用作 iframe。有关详细步骤,请参阅 设置 Google reCAPTCHA 的最后几个步骤。

附加资源

Keycloak 收集的个人数据

默认情况下,Keycloak 收集以下数据

  • 基本用户个人资料数据,例如用户电子邮件、名字和姓氏。

  • 用于社交帐户的基本用户个人资料数据以及使用社交登录时对社交帐户的引用。

  • 出于审计和安全目的收集的设备信息,例如 IP 地址、操作系统名称和浏览器名称。

Keycloak 中收集的信息是高度可定制的。进行自定义时,以下准则适用

  • 注册和帐户表单可以包含自定义字段,例如生日、性别和国籍。管理员可以将 Keycloak 配置为从社交提供商或用户存储提供商(例如 LDAP)检索数据。

  • Keycloak 收集用户凭据,例如密码、OTP 代码和 WebAuthn 公钥。此信息已加密并保存在数据库中,因此 Keycloak 管理员不可见。每种类型的凭据都可以包含非机密元数据,这些元数据对管理员可见,例如用于哈希密码的算法以及用于哈希密码的哈希迭代次数。

  • 启用授权服务和 UMA 支持后,Keycloak 可以保存有关特定用户是所有者的某些对象的信息。

管理用户会话

当用户登录 realm 时,Keycloak 会为每个用户维护一个用户会话,并记住用户在会话中访问的每个客户端。Realm 管理员可以对每个用户会话执行多项操作

  • 查看 realm 的登录统计信息。

  • 查看活跃用户以及他们的登录位置。

  • 将用户从其会话中注销。

  • 撤销令牌。

  • 设置令牌超时。

  • 设置会话超时。

管理会话

要查看 Keycloak 中活动客户端和会话的顶层视图,请单击菜单中的 Sessions(会话)。

会话

Sessions tab

注销所有活动会话

您可以注销 realm 中的所有用户。从 Action(操作)列表中,选择 Sign out all active sessions(注销所有活动会话)。所有 SSO cookie 都将失效。Keycloak 通过使用 Keycloak OIDC 客户端适配器通知客户端注销事件。在活动浏览器会话中请求身份验证的客户端必须重新登录。SAML 等客户端类型不会收到后通道注销请求。

单击 Sign out all active sessions(注销所有活动会话)不会撤销未完成的访问令牌。未完成的令牌必须自然过期。对于使用 Keycloak OIDC 客户端适配器的客户端,您可以推送撤销策略来撤销令牌,但这不适用于其他适配器。

查看客户端会话

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 单击客户端以查看该客户端的会话。

  3. 单击 Sessions(会话)选项卡。

    客户端会话

    Client sessions

查看用户会话

步骤
  1. 在菜单中点击用户

  2. 单击用户以查看该用户的会话。

  3. 单击 Sessions(会话)选项卡。

    用户会话

    User sessions

撤销活动会话

如果您的系统遭到入侵,您可以撤销所有活动会话和访问令牌。

步骤
  1. 单击菜单中的 Sessions(会话)。

  2. Actions(操作)列表中,选择 Revocation(撤销)。

    撤销

    Revocation

  3. 使用此控制台指定会话或在该日期和时间之前颁发的令牌失效的日期和时间。

    • 单击 Set to now(设置为现在)将策略设置为当前日期和时间。

    • 单击 Push(推送)以将此撤销策略推送到任何已注册且使用 Keycloak OIDC 客户端适配器的 OIDC 客户端。

会话和令牌超时

Keycloak 在 Realm settings(Realm 设置)菜单中的 Sessions(会话)和 Tokens(令牌)选项卡中,包含了对会话、cookie 和令牌超时的控制。

会话选项卡

Sessions Tab

配置 描述

SSO 会话空闲

此设置仅适用于 OIDC 客户端。如果用户不活动时间超过此超时时间,则用户会话将失效。当客户端请求身份验证或发送刷新令牌请求时,此超时值会重置。Keycloak 会在空闲超时时间中增加一个时间窗口,然后会话失效才会生效。请参阅本节稍后的注意

SSO 会话最大值

用户会话过期的最长时间。

SSO 会话空闲记住我

此设置类似于标准的 SSO 会话空闲配置,但专门针对启用 Remember Me(记住我)的登录。用户在登录时单击 Remember Me(记住我)时,可以指定更长的会话空闲超时时间。此设置是可选配置,如果其值不大于零,则它使用与 SSO 会话空闲配置相同的空闲超时时间。

SSO 会话最大值记住我

此设置类似于标准的 SSO 会话最大值,但专门针对 Remember Me(记住我)登录。用户在登录时单击 Remember Me(记住我)时,可以指定更长的会话。此设置是可选配置,如果其值不大于零,则它使用与 SSO 会话最大值配置相同的会话生命周期。

客户端会话空闲

客户端会话的空闲超时时间。如果用户不活动时间超过此超时时间,则客户端会话将失效,并且刷新令牌请求会延长空闲超时时间。此设置永远不会影响通用的 SSO 用户会话,它是唯一的。请注意,SSO 用户会话是零个或多个客户端会话的父级,对于用户登录的每个不同的客户端应用程序,都会创建一个客户端会话。此值应指定比 SSO 会话空闲 更短的空闲超时时间。用户可以在 Advanced Settings(高级设置)客户端选项卡中为单个客户端覆盖它。此设置是可选配置,当设置为零时,它使用与 SSO 会话空闲配置相同的空闲超时时间。

客户端会话最大值

客户端会话的最长时间,以及刷新令牌过期和失效之前的最长时间。与之前的选项一样,此设置永远不会影响 SSO 用户会话,并且应指定比 SSO 会话最大值 更短的值。用户可以在 Advanced Settings(高级设置)客户端选项卡中为单个客户端覆盖它。此设置是可选配置,当设置为零时,它使用与 SSO 会话最大值配置相同的最大超时时间。

离线会话空闲

此设置用于离线访问。会话保持空闲的时间量,超过此时间后,Keycloak 将撤销其离线令牌。Keycloak 会在空闲超时时间中增加一个时间窗口,然后会话失效才会生效。请参阅本节稍后的注意

离线会话最大值限制

此设置用于离线访问。如果此标志为 Enabled(启用),则“离线会话最大值”可以控制离线令牌保持活动状态的最长时间,而与用户活动无关。如果此标志为 Disabled(禁用),则离线会话永远不会因生命周期而过期,而只会因空闲而过期。激活此选项后,可以配置离线会话最大值(realm 级别的全局选项)和 Client Offline Session Max(客户端“高级设置”选项卡中的特定客户端级别选项)。

离线会话最大值

此设置用于离线访问,它是 Keycloak 撤销相应离线令牌之前的最长时间。此选项控制离线令牌保持活动状态的最长时间,而与用户活动无关。

登录超时

登录必须花费的总时间。如果身份验证花费的时间超过此时间,则用户必须重新开始身份验证过程。

登录操作超时

用户在身份验证过程中的任何一个页面上可以花费的最长时间。

令牌选项卡

Tokens Tab

配置 描述

默认签名算法

用于为 realm 分配令牌的默认算法。

撤销刷新令牌

Enabled(启用)时,Keycloak 将撤销刷新令牌并颁发客户端必须使用的另一个令牌。此操作适用于执行刷新令牌流程的 OIDC 客户端。

访问令牌生命周期

当 Keycloak 创建 OIDC 访问令牌时,此值控制令牌的生命周期。

隐式流程的访问令牌生命周期

对于隐式流程,Keycloak 不提供刷新令牌。对于通过隐式流程创建的访问令牌,存在单独的超时时间。

客户端登录超时

客户端必须在 OIDC 中完成授权码流程的最长时间。

用户发起的动作生命周期

用户动作权限过期的最长时间。保持此值较短,因为用户通常会对自行创建的动作做出快速反应。

默认管理员发起的动作生命周期

管理员发送给用户的动作权限过期的最长时间。保持此值较长,以便管理员可以向离线用户发送电子邮件。管理员可以在颁发令牌之前覆盖默认超时时间。

电子邮件验证

指定电子邮件验证的独立超时时间。

IdP 帐户电子邮件验证

指定 IdP 帐户电子邮件验证的独立超时时间。

忘记密码

指定忘记密码的独立超时时间。

执行操作

指定执行操作的独立超时时间。

以下逻辑仅在持久用户会话未激活时应用

对于空闲超时,会话处于活动状态的时间窗口为两分钟。例如,当您将超时时间设置为 30 分钟时,会话将在 32 分钟后过期。

在集群和跨数据中心环境中,某些情况下需要执行此操作,在这些环境中,令牌在一个集群节点上刷新,时间比过期时间提前一小段时间,而其他集群节点错误地认为会话已过期,因为它们尚未收到来自刷新节点的关于成功刷新的消息。

离线访问

离线访问登录期间,客户端应用程序请求离线令牌而不是刷新令牌。客户端应用程序保存此离线令牌,如果用户注销,则可以使用它进行将来的登录。如果您的应用程序需要在用户未在线时代表用户执行离线操作,则此操作非常有用。例如,定期数据备份。

客户端应用程序负责将离线令牌持久化存储,然后使用它从 Keycloak 服务器检索新的访问令牌。

刷新令牌和离线令牌之间的区别在于,离线令牌永不过期,并且不受 SSO 会话空闲 超时和 SSO 会话最大值 生命周期限制。离线令牌在用户注销后仍然有效。您必须每三十天至少使用一次离线令牌进行刷新令牌操作,或者按照离线会话空闲的值进行操作。

如果您启用离线会话最大值限制,即使您使用离线令牌进行刷新令牌操作,离线令牌也会在 60 天后过期。您可以在管理控制台中更改此值,离线会话最大值

当使用离线访问时,客户端空闲和最大超时可以在客户端级别被覆盖。客户端 Advanced Settings(高级设置)选项卡中的 Client Offline Session Idle(客户端离线会话空闲)和 Client Offline Session Max(客户端离线会话最大值)选项允许您为特定应用程序设置更短的离线超时时间。请注意,客户端会话值也控制刷新令牌过期时间,但它们永远不会影响全局离线用户 SSO 会话。只有当 realm 级别 Offline Session Max Limited(离线会话最大值限制)设置为 Enabled(启用)时,才会在客户端中评估 Client Offline Session Max(客户端离线会话最大值)选项。

如果您启用撤销刷新令牌选项,则每个离线令牌只能使用一次。刷新后,您必须存储来自刷新响应的新离线令牌,而不是之前的令牌。

用户可以在用户帐户控制台中查看和撤销 Keycloak 授予他们的离线令牌。管理员可以在管理控制台的 Consents(授权许可)选项卡中撤销单个用户的离线令牌。管理员可以在每个客户端的 Offline Access(离线访问)选项卡中查看所有已颁发的离线令牌。管理员可以通过设置撤销策略来撤销离线令牌。

要颁发离线令牌,用户必须具有 realm 级 offline_access 角色的角色映射。客户端还必须在其范围中具有该角色。客户端必须将 offline_access 客户端范围添加为角色的 Optional client scope(可选客户端范围),默认情况下已完成此操作。

客户端可以通过在向 Keycloak 发送授权请求时添加参数 scope=offline_access 来请求离线令牌。当您使用 Keycloak OIDC 客户端适配器访问应用程序的安全 URL(例如,https://#:8080/customer-portal/secured?scope=offline_access)时,它会自动添加此参数。如果您在身份验证请求正文中包含 scope=offline_access,则直接访问授权和服务帐户也支持离线令牌。

默认情况下,Keycloak 将其离线用户和离线客户端会话的内部缓存限制为 10000 个条目,这将减少离线会话的总体内存使用量。从内存中逐出的项目将在需要时按需从数据库加载。要为缓存设置不同的大小,请编辑 Keycloak 的缓存配置文件,为这些缓存设置 <memory max-count="..."/>

如果您禁用了 persistent-user-sessions 功能,则可以使用配置选项来缩短导入的离线会话的生命周期,从而降低内存需求。此类会话将在指定的生命周期后从 Infinispan 缓存中逐出,但仍可在数据库中使用。这将降低内存消耗,尤其是在部署了大量离线会话的情况下。

要指定离线用户会话的生命周期覆盖,请使用以下参数启动 Keycloak 服务器

--spi-user-sessions-infinispan-offline-session-cache-entry-lifespan-override=<lifespan-in-seconds>

离线客户端会话类似

--spi-user-sessions-infinispan-offline-client-session-cache-entry-lifespan-override=<lifespan-in-seconds>

瞬态会话

您可以在 Keycloak 中执行瞬态会话。当使用瞬态会话时,Keycloak 在成功身份验证后不会创建用户会话。Keycloak 为当前请求的范围创建一个临时的瞬态会话,该请求成功验证了用户身份。Keycloak 可以在身份验证后使用瞬态会话运行 协议映射器

当令牌通过瞬态会话颁发时,令牌的 sidsession_state 通常为空。因此,在瞬态会话期间,客户端应用程序无法刷新令牌或验证特定会话。有时这些操作是不必要的,因此您可以避免持久化用户会话而产生的额外资源使用。此会话节省了性能、内存和网络通信(在集群和跨数据中心环境)资源。

目前,仅在禁用令牌刷新的服务帐户身份验证期间自动使用瞬态会话。请注意,除非通过客户端开关 Use refresh tokens for client credentials grant 显式启用令牌刷新,否则在服务帐户身份验证期间会自动禁用令牌刷新。

使用角色和组分配权限

角色和组具有相似的目的,即为用户提供访问权限和使用应用程序的权限。组是用户的集合,您可以在其中应用角色和属性。角色定义特定的应用程序权限和访问控制。

一个角色通常适用于一种类型的用户。例如,一个组织可能包括 adminusermanageremployee 角色。应用程序可以将访问权限和许可分配给角色,然后将多个用户分配给该角色,以便用户具有相同的访问权限和许可。例如,Admin Console 具有允许用户访问 Admin Console 不同部分的角色。

角色有一个全局命名空间,每个客户端也有其自己的专用命名空间,可以在其中定义角色。

创建 realm 角色

Realm 级别的角色是定义角色的命名空间。要查看角色列表,请单击菜单中的 Realm Roles(Realm 角色)

roles

步骤
  1. 单击 Create Role(创建角色)

  2. 输入 Role Name(角色名称)

  3. 输入 Description(描述)

  4. 点击 保存

description(描述) 字段可以通过使用 ${var-name} 字符串指定替换变量来实现本地化。本地化值在主题属性文件中配置到您的主题。有关更多详细信息,请参阅 Server Developer Guide(服务器开发者指南)

客户端角色

客户端角色是客户端专用的命名空间。每个客户端都有其自己的命名空间。客户端角色在每个客户端的 Roles(角色) 选项卡下进行管理。您与此 UI 的交互方式与对 realm 级别角色相同。

将角色转换为复合角色

任何 realm 或客户端级别的角色都可以成为复合角色复合角色是指具有一个或多个关联角色的角色。当复合角色映射到用户时,用户将获得与复合角色关联的角色。这种继承是递归的,因此用户也会继承任何复合角色的复合角色。但是,我们建议不要过度使用复合角色。

步骤
  1. 单击菜单中的 Realm Roles(Realm 角色)

  2. 单击要转换的角色。

  3. Action(操作) 列表中,选择 Add associated roles(添加关联角色)

复合角色

Composite role

角色选择 UI 将显示在页面上,您可以将 realm 级别和客户端级别的角色与您正在创建的复合角色关联。

在此示例中,employee(员工) realm 级别角色与 developer(开发者) 复合角色关联。任何具有 developer(开发者) 角色的用户也将继承 employee(员工) 角色。

在创建令牌和 SAML 断言时,任何复合角色也会将其关联角色添加到发送回客户端的身份验证响应的声明和断言中。

分配角色映射

您可以通过用户的 Role Mappings(角色映射) 选项卡为用户分配角色映射。

步骤
  1. 在菜单中点击用户

  2. 单击要执行角色映射的用户。

  3. 单击 Role mappings(角色映射) 选项卡。

  4. 单击 Assign role(分配角色)

  5. 从对话框中选择要分配给用户的角色。

  6. 单击 分配

角色映射

Role mappings

在前面的示例中,我们将复合角色 developer(开发者) 分配给用户。该角色是在 复合角色 主题中创建的。

有效角色映射

Effective role mappings

当分配 developer(开发者) 角色时,与 developer(开发者) 复合角色关联的 employee(员工) 角色将显示为 Inherited(已继承) “True”。Inherited(已继承) 角色是显式分配给用户的角色以及从复合角色继承的角色。

使用默认角色

当用户通过 身份代理 创建或导入时,使用默认角色自动分配用户角色映射。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击 User registration(用户注册) 选项卡。

    默认角色

    Default roles

此屏幕截图显示已存在一些默认角色

角色范围映射

在创建 OIDC 访问令牌或 SAML 断言时,用户角色映射将成为令牌或断言中的声明。应用程序使用这些声明来对应用程序控制的资源做出访问决策。Keycloak 对访问令牌进行数字签名,应用程序重用这些令牌来调用远程安全 REST 服务。但是,这些令牌具有相关风险。攻击者可以获取这些令牌并使用其权限来危害您的网络。为防止这种情况,请使用角色范围映射

角色范围映射限制了访问令牌内声明的角色。当客户端请求用户身份验证时,它收到的访问令牌仅包含为客户端范围显式指定的角色映射。结果是,每个单独访问令牌的权限受到限制,而不是让客户端访问用户的所有权限。

默认情况下,每个客户端都获取用户的所有角色映射。您可以查看客户端的角色映射。

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 单击客户端以转到详细信息。

  3. 单击 Client scopes(客户端范围) 选项卡。

  4. 单击带有 Dedicated scope and mappers for this client(此客户端的专用范围和映射器) 的行中的链接

  5. 单击 Scope(范围) 选项卡。

完整范围

Full scope

默认情况下,范围的有效角色是 realm 中声明的每个角色。要更改此默认行为,请将 Full Scope Allowed(允许完整范围) 切换为 OFF(关闭),并在每个客户端中声明您需要的特定角色。您还可以使用 客户端范围 为一组客户端定义相同的角色范围映射。

部分范围

Partial scope

有关将角色添加到令牌的算法的详细信息,请参阅 令牌角色映射部分

Keycloak 中的组管理每个用户的通用属性集和角色映射。用户可以是任意数量的组的成员,并继承分配给每个组的属性和角色映射。

要管理组,请单击菜单中的 Groups(组)

groups

组是分层的。一个组可以有多个子组,但一个组只能有一个父组。子组从其父组继承属性和角色映射。用户也从其父组继承属性和角色映射。

如果您有一个父组和一个子组,并且一个用户仅属于子组,则子组中的用户将继承父组和子组的属性和角色映射。

组的层次结构有时使用组路径表示。路径是表示特定组层次结构的完整名称列表,从上到下并用斜杠 / 分隔(类似于文件系统中的文件)。例如,路径可以是 /top/level1/level2,这意味着 top 是顶级组,是 level1 的父组,而 level1 又是 level2 的父组。此路径明确地表示组 level2 的层次结构。

由于历史原因,Keycloak 不会转义组名称本身中的斜杠。因此,top 下名为 level1/group 的组使用路径 /top/level1/group,这具有误导性。可以使用选项 --spi-group-jpa-escape-slashes-in-group-path 将 Keycloak 启动为 true,然后名称中的斜杠将使用字符 ~ 转义。转义字符标记斜杠是名称的一部分,没有层次结构意义。当转义时,之前的路径示例将为 /top/level1~/group

bin/kc.[sh|bat] start --spi-group-jpa-escape-slashes-in-group-path=true

以下示例包括一个顶级 Sales(销售) 组和一个子级 North America(北美) 子组。

要添加组

  1. 单击组。

  2. 单击 Create group(创建组)

  3. 输入组名称。

  4. 单击“创建”。

  5. 单击组名称。

    将显示组管理页面。

    group

您定义的属性和角色映射由组以及作为该组成员的用户继承。

要将用户添加到组

  1. 在菜单中点击用户

  2. 单击要执行角色映射的用户。如果未显示用户,请单击 View all users(查看所有用户)

  3. 单击 Groups(组)

  4. 单击 Join Group(加入组)

  5. 从对话框中选择一个组。

  6. Available Groups(可用组) 树中选择一个组。

  7. 单击 Join(加入)

    加入组

    user groups

要从用户中删除组

  1. 在菜单中点击用户

  2. 单击要从组中删除的用户。

  3. 单击组表格行上的 Leave(离开)

在此示例中,用户 jimlincolnNorth America(北美) 组中。您可以在该组的 Members(成员) 选项卡下看到显示的 jimlincoln

组成员资格

group membership

组与角色的比较

组和角色有一些相似之处和不同之处。在 Keycloak 中,组是用户的集合,您可以在其中应用角色和属性。角色定义用户类型,应用程序将权限和访问控制分配给角色。

复合角色 与组类似,因为它们提供相同的功能。它们之间的区别在于概念。复合角色将权限模型应用于一组服务和应用程序。使用复合角色来管理应用程序和服务。

组侧重于用户集合及其在组织中的角色。使用组来管理用户。

使用默认组

要自动为通过 身份代理 创建或导入的任何用户分配组成员资格,您可以使用默认组。

  1. 在菜单中单击“Realm 设置”。

  2. 单击 User registration(用户注册) 选项卡。

  3. 单击 Default Groups(默认组) 选项卡。

    默认组

    Default groups

此屏幕截图显示已存在一些默认组

配置身份验证

本章涵盖了几个身份验证主题。这些主题包括

  • 强制执行严格的密码和一次性密码 (OTP) 策略。

  • 管理不同的凭据类型。

  • 使用 Kerberos 登录。

  • 禁用和启用内置凭据类型。

密码策略

当 Keycloak 创建 realm 时,它不会将密码策略与 realm 关联。您可以设置一个简单的密码,对其长度、安全性或复杂性没有限制。简单的密码在生产环境中是不可接受的。Keycloak 通过管理控制台提供了一组密码策略。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 策略 (Policies) 选项卡。

  3. 添加策略 (Add policy) 下拉框中选择要添加的策略。

  4. 输入适用于所选策略的值。

  5. 点击 保存

    密码策略

    Password Policy

保存策略后,Keycloak 会对新用户强制执行该策略。

新策略对现有用户无效。因此,请确保在 realm 创建之初就设置密码策略,或者向现有用户添加 “更新密码 (Update password)” 操作,或者使用 “密码过期 (Expire password)” 以确保用户在接下来的 “N” 天内更新其密码,这将实际适应新的密码策略。

密码策略类型

HashAlgorithm

密码不会以明文形式存储。在存储或验证之前,Keycloak 使用标准哈希算法对密码进行哈希处理。

下表显示了支持的密码哈希算法。

哈希算法 描述

argon2

Argon2(非 FIPS 部署的默认算法)

pbkdf2-sha512

PBKDF2 with SHA512(FIPS 部署的默认算法)

pbkdf2-sha256

PBKDF2 with SHA256

pbkdf2

PBKDF2 with SHA1(已弃用)

强烈建议尽可能使用 Argon2,因为与 PBKDF2 相比,它对 CPU 的要求显著降低,同时更安全。

可以使用 --spi-password-hashing-provider-default=<algorithm> 配置服务器的默认密码哈希算法。

为了防止过度的内存和 CPU 使用率,Argon2 并行计算哈希值默认限制为 JVM 可用的核心数。要配置 Argon2 哈希提供程序,请使用其提供程序选项。

请参阅 服务器开发人员指南 (Server Developer Guide),了解如何添加您自己的哈希算法。

如果您更改哈希算法,则存储中的密码哈希值在用户登录之前不会更改。

哈希迭代次数

指定 Keycloak 在存储或验证之前对密码进行哈希处理的次数。默认值为 -1,它使用所选哈希算法的默认哈希迭代次数,如下表所示。

哈希算法 默认哈希迭代次数

argon2

5

pbkdf2-sha512

210,000

pbkdf2-sha256

600,000

pbkdf2

1,300,000

在大多数情况下,哈希迭代次数不应从建议的默认值更改。较低的迭代次数提供的安全性不足,而较高的迭代次数会导致更高的 CPU 功耗要求。

数字

密码字符串中所需的数字位数。

小写字符

密码字符串中所需的小写字母数。

大写字符

密码字符串中所需的大写字母数。

特殊字符

密码字符串中所需的特殊字符数。

非用户名

密码不能与用户名相同。

非电子邮件

密码不能与用户的电子邮件地址相同。

正则表达式

密码必须匹配一个或多个定义的 Java 正则表达式模式。有关这些表达式的语法,请参阅 Java 的正则表达式文档

密码过期

密码有效的天数。当天数过期后,用户必须更改其密码。

非最近使用过的密码

密码不能是用户已经使用过的密码。Keycloak 存储已使用密码的历史记录。存储的旧密码数量可在 Keycloak 中配置。

非最近使用过的密码(天数)

密码不能在配置的时间段(以天为单位)内重复使用。如果新密码是在此期间内最后一次设置的,则将强制用户提供不同的密码。

密码黑名单

密码不得在黑名单文件中。

  • 黑名单文件是 UTF-8 纯文本文件,使用 Unix 行尾符。每一行代表一个被列入黑名单的密码。

  • Keycloak 以不区分大小写的方式比较密码。

  • 黑名单文件的值必须是黑名单文件的名称,例如,100k_passwords.txt

  • 默认情况下,黑名单文件相对于 ${kc.home.dir}/data/password-blacklists/ 解析。使用以下方式自定义此路径

    • keycloak.password.blacklists.path 系统属性。

    • passwordBlacklist 策略 SPI 配置的 blacklistsPath 属性。要使用 CLI 配置黑名单文件夹,请使用 --spi-password-policy-password-blacklist-blacklists-path=/path/to/blacklistsFolder

关于误报的说明

当前实现使用 BloomFilter 进行快速且内存高效的包含性检查,例如给定的密码是否包含在黑名单中,但可能存在误报。

  • 默认情况下,使用 0.01% 的误报概率。

  • 要通过 CLI 配置更改误报概率,请使用 --spi-password-policy-password-blacklist-false-positive-probability=0.00001

最大身份验证年龄

指定用户在无需重新身份验证的情况下更新密码的最大身份验证年龄(以秒为单位)。值为 0 表示用户在更新密码之前始终必须使用当前密码重新进行身份验证。有关此策略的一些其他详细信息,请参阅 AIA 部分

在管理控制台的 必需操作 (Required Actions) 选项卡中配置必需操作 更新密码 (Update Password) 时,也可以配置最大身份验证年龄。更好的选择是使用必需操作进行配置,因为 *最大身份验证年龄* 密码策略将来可能会被弃用/删除。

一次性密码 (OTP) 策略

Keycloak 具有多个策略,用于设置 FreeOTP 或 Google Authenticator 一次性密码生成器。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 策略 (Policy) 选项卡。

  3. 点击 OTP 策略 (OTP Policy) 选项卡。

OTP 策略

OTP Policy

Keycloak 在 OTP 设置页面上生成一个 QR 码,该 QR 码基于 OTP 策略 (OTP Policy) 选项卡中配置的信息。FreeOTP 和 Google Authenticator 在配置 OTP 时扫描 QR 码。

基于时间或基于计数器的一次性密码

Keycloak 中 OTP 生成器可用的算法是基于时间和基于计数器的。

使用基于时间的一次性密码 (TOTP),令牌生成器将哈希当前时间和共享密钥。服务器通过比较时间窗口内的哈希值与提交的值来验证 OTP。TOTP 在短时间内有效。

使用基于计数器的一次性密码 (HOTP),Keycloak 使用共享计数器而不是当前时间。Keycloak 服务器在每次成功的 OTP 登录时递增计数器。有效的 OTP 在成功登录后会更改。

TOTP 比 HOTP 更安全,因为可匹配的 OTP 在短时间内有效,而 HOTP 的 OTP 在不确定的时间内有效。HOTP 比 TOTP 更用户友好,因为输入 OTP 没有时间限制。

HOTP 每次服务器递增计数器时都需要数据库更新。在高负载期间,此更新会消耗身份验证服务器的性能。为了提高效率,TOTP 不会记住使用过的密码,因此无需执行数据库更新。缺点是在有效时间间隔内可以重用 TOTP。

TOTP 配置选项

OTP 哈希算法

默认算法为 SHA1。其他更安全的选项是 SHA256 和 SHA512。

数字位数

OTP 的长度。短 OTP 用户友好、更易于键入且更易于记住。较长的 OTP 比短 OTP 更安全。

查找窗口

服务器尝试匹配哈希的时间间隔数。如果 TOTP 生成器或身份验证服务器的时钟不同步,则 Keycloak 中会显示此选项。默认值 1 已足够。例如,如果令牌的时间间隔为 30 秒,则默认值 1 表示它将接受 90 秒窗口内的有效令牌(时间间隔 30 秒 + 向前查找 30 秒 + 向后查找 30 秒)。此值的每次递增都会将有效窗口增加 60 秒(向前查找 30 秒 + 向后查找 30 秒)。

OTP 令牌周期

服务器匹配哈希的时间间隔(以秒为单位)。每次间隔过去,令牌生成器都会生成一个 TOTP。

可重用代码

确定是否可以在身份验证过程中重用 OTP 令牌,或者用户是否需要等待下一个令牌。默认情况下,用户无法重用这些令牌,管理员需要显式指定可以重用这些令牌。

HOTP 配置选项

OTP 哈希算法

默认算法为 SHA1。其他更安全的选项是 SHA256 和 SHA512。

数字位数

OTP 的长度。短 OTP 用户友好、更易于键入且更易于记住。较长的 OTP 比短 OTP 更安全。

查找窗口

服务器尝试匹配哈希的前后间隔数。如果 TOTP 生成器或身份验证服务器的时钟不同步,则 Keycloak 中会显示此选项。默认值 1 已足够。Keycloak 中提供此选项是为了涵盖用户计数器超前于服务器的情况。

初始计数器

初始计数器的值。

身份验证流程

身份验证流程 是登录、注册和其他 Keycloak 工作流程期间的身份验证、屏幕和操作的容器。

内置流程

Keycloak 有几个内置流程。您无法修改这些流程,但可以更改流程的需求以满足您的需要。

步骤
  1. 点击菜单中的 身份验证

  2. 点击列表中的 Browser 项以查看详细信息。

浏览器流程

Browser Flow

身份验证类型

要执行的身份验证或操作的名称。如果身份验证已缩进,则它位于子流程中。它可能会执行,也可能不会执行,具体取决于其父级的行为。

  1. Cookie

    用户首次成功登录时,Keycloak 会设置会话 Cookie。如果 Cookie 已设置,则此身份验证类型成功。由于 Cookie 提供程序返回成功,并且此流程级别的每次执行都是备选的,因此 Keycloak 不会执行任何其他操作。这会导致成功登录。

  2. Kerberos

    此身份验证器默认情况下已禁用,并在浏览器流程期间跳过。

  3. 身份提供商重定向器

    此操作通过 操作 (Actions) > 配置 (Config) 链接进行配置。它重定向到另一个 IdP 进行 身份代理

  4. 表单

    由于此子流程标记为备选,如果 Cookie 身份验证类型通过,则不会执行此子流程。此子流程包含需要执行的其他身份验证类型。Keycloak 加载此子流程的执行并处理它们。

第一个执行是 用户名密码表单 (Username Password Form),这是一种身份验证类型,用于呈现用户名和密码页面。它被标记为必需,因此用户必须输入有效的用户名和密码。

第二个执行是 Browser - Conditional OTP 子流程。此子流程是有条件的,并根据 Condition - User Configured 执行的结果执行。如果结果为 true,Keycloak 会为此子流程加载执行并处理它们。

下一个执行是 Condition - User Configured 身份验证。此身份验证检查 Keycloak 是否为用户配置了流程中的其他执行。只有当用户配置了 OTP 凭据时,Browser - Conditional OTP 子流程才会执行。

最后的执行是 OTP Form。Keycloak 将此执行标记为必需的,但它仅在用户设置了 OTP 凭据时运行,因为在有条件的子流程中进行了设置。如果未设置,用户将不会看到 OTP 表单。

要求

一组控制操作执行的单选按钮。

必需

流程中所有必需的元素都必须按顺序成功执行。如果必需的元素失败,流程将终止。

备选

只需单个元素成功执行,流程即可评估为成功。由于必需的流程元素足以将流程标记为成功,因此包含必需流程元素的流程中的任何备选流程元素都不会执行。

已禁用

该元素不计入流程是否成功的标记。

有条件的

此要求类型仅在子流程上设置。

  • 有条件的子流程包含执行。这些执行必须评估为逻辑语句。

  • 如果所有执行都评估为true,则有条件的子流程的作用类似于必需

  • 如果任何执行评估为false,则有条件的子流程的作用类似于已禁用

  • 如果您未设置执行,则有条件的子流程的作用类似于已禁用

  • 如果流程包含执行,且该流程未设置为有条件的,则 Keycloak 不会评估这些执行,并且这些执行在功能上被视为已禁用

创建流程

设计流程时,重要的功能和安全注意事项适用。

要创建流程,请执行以下操作

步骤
  1. 点击菜单中的 身份验证

  2. 点击 创建流程

您可以复制然后修改现有流程。点击“操作列表”(行尾的三个点),点击 复制,然后输入新流程的名称。

创建新流程时,您必须首先创建具有以下选项的顶层流程

名称

流程的名称。

描述

您可以为流程设置的描述。

顶层流程类型

流程的类型。类型 client 仅用于客户端(应用程序)的身份验证。对于所有其他情况,请选择 basic

创建顶层流程

Top Level Flow

当 Keycloak 创建流程后,Keycloak 会显示 添加步骤添加子流程 按钮。

一个空的新流程

New Flow

三个因素决定了流程和子流程的行为。

  • 流程和子流程的结构。

  • 流程内的执行

  • 子流程和执行中设置的要求。

执行具有各种各样的操作,从发送重置电子邮件到验证 OTP。使用 添加步骤 按钮添加执行。

添加身份验证执行

Adding an Authentication Execution

身份验证执行可以选择配置参考值。身份验证方法参考 (AMR) 协议映射器可以利用此值来填充 OIDC 访问令牌和 ID 令牌中的 amr 声明(有关 AMR 声明的更多信息,请参阅 RFC-8176)。当为客户端配置了身份验证方法参考 (AMR) 协议映射器时,它将使用用户在身份验证流程期间成功完成的任何身份验证器执行的参考值来填充 amr 声明。

添加身份验证器参考值

Configuring an Authenticator Reference Value

存在两种类型的执行,自动执行交互式执行自动执行 类似于 Cookie 执行,并将自动在流程中执行其操作。交互式执行 会暂停流程以获取输入。成功执行的执行将其状态设置为成功。要使流程完成,它至少需要一个状态为成功的执行。

您可以使用 添加子流程 按钮将子流程添加到顶层流程。添加子流程 按钮显示 创建执行流程 页面。此页面类似于 创建顶层表单 页面。区别在于 流程类型 可以是 basic(默认)或 formform 类型构建一个为用户生成表单的子流程,类似于内置的 Registration 流程。子流程的成功取决于其执行的评估结果,包括其包含的子流程。有关子流程如何工作的深入解释,请参阅 执行要求部分

添加执行后,检查要求是否具有正确的值。

流程中的所有元素在元素旁边都有一个 删除 选项。某些执行具有 ⚙️ 菜单项(齿轮图标)来配置执行。也可以使用 添加步骤添加子流程 链接将执行和子流程添加到子流程。

由于执行顺序很重要,您可以通过拖动其名称来上下移动执行和子流程。

当您配置身份验证流程以确认您的设置中不存在安全漏洞时,请务必正确测试您的配置。我们建议您测试各种极端情况。例如,考虑在身份验证之前从用户的帐户中删除各种凭据时,测试用户的身份验证行为。

例如,当在流程中将第二因素身份验证器(如 OTP 表单或 WebAuthn 身份验证器)配置为 REQUIRED,并且用户没有特定类型的凭据时,用户将能够在身份验证本身期间设置特定凭据。这种情况意味着用户并非使用此凭据进行身份验证,因为他是在身份验证期间设置的。因此,对于浏览器身份验证,请确保使用某些第一因素凭据(如密码或 WebAuthn 无密码身份验证器)配置您的身份验证流程。

创建无密码浏览器登录流程

为了说明流程的创建,本节描述了创建高级浏览器登录流程。此流程的目的是允许用户选择使用 WebAuthn 以无密码方式登录,或使用密码和 OTP 进行双因素身份验证。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 流程 选项卡。

  3. 点击 创建流程

  4. 输入 Browser Password-less 作为名称。

  5. 单击“创建”。

  6. 点击 添加执行

  7. 从列表中选择 Cookie

  8. 点击 添加

  9. Cookie 身份验证类型选择 备选,将其要求设置为备选。

  10. 点击 添加步骤

  11. 从列表中选择 Kerberos

  12. 点击 添加

  13. 点击 添加步骤

  14. 从列表中选择 身份提供商重定向器

  15. 点击 添加

  16. 身份提供商重定向器 身份验证类型选择 备选,将其要求设置为备选。

  17. 点击 添加子流程

  18. 输入 Forms 作为名称。

  19. 点击 添加

  20. Forms 身份验证类型选择 备选,将其要求设置为备选。

    与浏览器流程的公共部分

    Passwordless browser login

  21. 点击 Forms 执行的 + 菜单。

  22. 选择 添加步骤

  23. 从列表中选择 用户名表单

  24. 点击 添加

在此阶段,表单需要用户名,但不需要密码。我们必须启用密码身份验证以避免安全风险。

  1. 点击 Forms 子流程的 + 菜单。

  2. 点击 添加子流程

  3. 输入 Authentication 作为名称。

  4. 点击 添加

  5. Authentication 身份验证类型选择 必需,将其要求设置为必需。

  6. 点击 Authentication 子流程的 + 菜单。

  7. 点击 添加步骤

  8. 从列表中选择 WebAuthn 无密码身份验证器

  9. 点击 添加

  10. Webauthn 无密码身份验证器 身份验证类型选择 备选,将其要求设置为备选。

  11. 点击 Authentication 子流程的 + 菜单。

  12. 点击 添加子流程

  13. 输入 Password with OTP 作为名称。

  14. 点击 添加

  15. Password with OTP 身份验证类型选择 备选,将其要求设置为备选。

  16. 点击 Password with OTP 子流程的 + 菜单。

  17. 点击 添加步骤

  18. 从列表中选择 密码表单

  19. 点击 添加

  20. 密码表单 身份验证类型选择 必需,将其要求设置为必需。

  21. 点击 Password with OTP 子流程的 + 菜单。

  22. 点击 添加步骤

  23. 从列表中选择 OTP 表单

  24. 点击 添加

  25. OTP 表单 身份验证类型点击 必需,将其要求设置为必需。

最后,更改绑定。

  1. 点击屏幕顶部的 操作 菜单。

  2. 从菜单中选择 绑定流程

  3. 点击 浏览器流程 下拉列表。

  4. 点击 保存

无密码浏览器登录

Passwordless browser login

输入用户名后,流程的工作方式如下

如果用户已记录 WebAuthn 无密码凭据,他们可以直接使用这些凭据登录。这是无密码登录。用户也可以选择 Password with OTP,因为 WebAuthn Passwordless 执行和 Password with OTP 流程都设置为 备选。如果它们设置为 必需,则用户必须输入 WebAuthn、密码和 OTP。

如果用户选择带有 WebAuthn passwordless 身份验证的 尝试其他方式 链接,则用户可以在 PasswordPasskey (WebAuthn 无密码) 之间进行选择。选择密码时,用户需要继续并使用分配的 OTP 登录。如果用户没有 WebAuthn 凭据,则用户必须输入密码,然后输入 OTP。如果用户没有 OTP 凭据,系统将要求他们记录一个。

由于 WebAuthn 无密码执行设置为 备选 而不是 必需,因此此流程永远不会要求用户注册 WebAuthn 凭据。要使用户拥有 Webauthn 凭据,管理员必须为用户添加必需的操作。通过以下方式执行此操作

  1. 在领域中启用 Webauthn 注册无密码 必需操作(请参阅 WebAuthn 文档)。

  2. 使用用户 凭据 管理菜单的 凭据重置 部分设置必需的操作。

创建如此高级的流程可能会产生副作用。例如,如果您启用重置用户密码的功能,则可以从密码表单访问此功能。在默认的 Reset Credentials 流程中,用户必须输入其用户名。由于用户已经在 Browser Password-less 流程中较早地输入了用户名,因此此操作对于 Keycloak 来说是不必要的,并且用户体验欠佳。要纠正此问题,您可以

  • 复制 Reset Credentials 流程。将其名称设置为 Reset Credentials for password-less,例如。

  • 点击 选择用户 步骤的 删除(垃圾桶图标)。

  • 操作 菜单中,选择 绑定流程,然后从下拉列表中选择 重置凭据流程,然后点击 保存

使用客户端策略选择身份验证流程

客户端策略 可用于根据特定条件(例如请求特定范围或使用 AuthenticationFlowSelectorExecutor 的 ACR(身份验证上下文类引用)与您偏好的条件相结合)动态选择身份验证流程。

AuthenticationFlowSelectorExecutor 允许您选择适当的身份验证流程,并设置选定流程完成后要应用的身份验证级别。

一种可能的配置涉及使用 ACRConditionAuthenticationFlowSelectorExecutor 结合使用。此设置使您能够根据请求的 ACR 选择身份验证流程,并将 ACR 值包含在使用 ACR 到 LoA 映射 的令牌中。

有关更多详细信息,请参阅 客户端策略

创建具有逐步提升机制的浏览器登录流程

本节描述了如何使用逐步提升机制创建高级浏览器登录流程。逐步提升身份验证的目的是允许基于用户的特定身份验证级别访问客户端或资源。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 流程 选项卡。

  3. 点击 创建流程

  4. 输入 Browser Incl Step up Mechanism 作为名称。

  5. 点击 保存

  6. 点击 添加执行

  7. 从列表中选择 Cookie

  8. 点击 添加

  9. Cookie 身份验证类型选择 备选,将其要求设置为备选。

  10. 点击 添加子流程

  11. 输入 Auth Flow 作为名称。

  12. 点击 添加

  13. Auth Flow 身份验证类型点击 备选,将其要求设置为备选。

现在,您配置第一个身份验证级别的流程。

  1. 点击 Auth Flow+ 菜单。

  2. 点击 添加子流程

  3. 输入 1st Condition Flow 作为名称。

  4. 点击 添加

  5. 1st Condition Flow 身份验证类型点击 有条件的,将其要求设置为有条件的。

  6. 点击 1st Condition Flow+ 菜单。

  7. 点击 添加条件

  8. 从列表中选择 条件 - 身份验证级别

  9. 点击 添加

  10. 条件 - 身份验证级别 身份验证类型点击 必需,将其要求设置为必需。

  11. 点击 ⚙️(齿轮图标)。

  12. 输入 Level 1 作为别名。

  13. 为身份验证级别 (LoA) 输入 1

  14. 将最大有效期设置为 36000。此值以秒为单位,相当于 10 小时,这是领域中设置的默认 SSO 会话最大时长 超时。因此,当用户使用此级别进行身份验证时,后续 SSO 登录可以重用此级别,并且用户无需使用此级别进行身份验证,直到用户会话结束,默认情况下为 10 小时。

  15. 点击 保存

    配置第一个身份验证级别的条件

    Authentication step up condition 1

  16. 点击 1st Condition Flow+ 菜单。

  17. 点击 添加步骤

  18. 从列表中选择 用户名密码表单

  19. 点击 添加

现在,您配置第二个身份验证级别的流程。

  1. 点击 Auth Flow+ 菜单。

  2. 点击 添加子流程

  3. 输入 2nd Condition Flow 作为别名。

  4. 点击 添加

  5. 2nd Condition Flow 身份验证类型点击 有条件的,将其要求设置为有条件的。

  6. 点击 2nd Condition Flow+ 菜单。

  7. 点击 添加条件

  8. 从项目列表中选择 条件 - 身份验证级别

  9. 点击 添加

  10. 条件 - 身份验证级别 身份验证类型点击 必需,将其要求设置为必需。

  11. 点击 ⚙️(齿轮图标)。

  12. 输入 Level 2 作为别名。

  13. 为身份验证级别 (LoA) 输入 2

  14. 将最大有效期设置为 0。因此,当用户进行身份验证时,此级别仅对当前身份验证有效,而对任何后续 SSO 身份验证均无效。因此,当请求此级别时,用户始终需要再次使用此级别进行身份验证。

  15. 点击 保存

    配置第二个身份验证级别的条件

    Autehtnication step up condition 2

  16. 点击 2nd Condition Flow+ 菜单。

  17. 点击 添加步骤

  18. 从列表中选择 OTP 表单

  19. 点击 添加

  20. OTP 表单 身份验证类型点击 必需,将其要求设置为必需。

最后,更改绑定。

  1. 点击屏幕顶部的 操作 菜单。

  2. 从列表中选择 绑定流程

  3. 在下拉列表中选择 浏览器流程

  4. 点击 保存

具有逐步提升机制的浏览器登录

Authentication step up flow

请求特定身份验证级别

要使用逐步提升机制,您需要在身份验证请求中指定请求的身份验证级别 (LoA)。claims 参数用于此目的

https://{DOMAIN}/realms/{REALMNAME}/protocol/openid-connect/auth?client_id={CLIENT-ID}&redirect_uri={REDIRECT-URI}&scope=openid&response_type=code&response_mode=query&nonce=exg16fxdjcu&claims=%7B%22id_token%22%3A%7B%22acr%22%3A%7B%22essential%22%3Atrue%2C%22values%22%3A%5B%22gold%22%5D%7D%7D%7D

claims 参数以 JSON 表示形式指定

claims= {
            "id_token": {
                "acr": {
                    "essential": true,
                    "values": ["gold"]
                }
            }
        }

Keycloak javascript 适配器支持轻松构建此 JSON 并在登录请求中发送它。有关更多详细信息,请参阅 securing apps 部分中的 Keycloak JavaScript adapter

您还可以使用更简单的参数 acr_values 而不是 claims 参数来请求特定级别作为非必要项。这在 OIDC 规范中有所提及。

您还可以为特定客户端配置默认级别,当参数 acr_values 或带有 acr 声明的 claims 参数不存在时,将使用该默认级别。有关更多详细信息,请参阅客户端 ACR 配置)。

要请求文本格式的 acr_values(例如 gold)而不是数字值,您可以配置 ACR 和 LoA 之间的映射。可以在 realm 级别(推荐)或客户端级别配置它。有关配置,请参阅ACR 到 LoA 映射

有关更多详细信息,请参阅官方 OIDC 规范

流程逻辑

先前配置的身份验证流程的逻辑如下
如果客户端请求高身份验证级别,即身份验证级别 2 (LoA 2),则用户必须执行完整的双因素身份验证:用户名/密码 + OTP。但是,如果用户已经在 Keycloak 中拥有会话,并且已使用用户名和密码(LoA 1)登录,则用户仅需提供第二个身份验证因素 (OTP)。

条件中的 Max Age 选项确定后续身份验证级别的有效时长(多少秒)。此设置有助于确定是否在后续身份验证期间再次要求用户出示身份验证因素。如果特定级别 X 由 claimsacr_values 参数请求,并且用户已经通过级别 X 身份验证,但该级别已过期(例如,最大年龄配置为 300 秒,用户在 310 秒之前进行了身份验证),则将要求用户使用该特定级别重新进行身份验证。但是,如果该级别尚未过期,则用户将被自动视为已通过该级别的身份验证。

Max Age 值设置为 0 意味着特定级别仅对本次身份验证有效。因此,每次请求该级别的重新身份验证都需要使用该级别再次进行身份验证。这对于应用程序中需要更高安全性的操作(例如,发送付款)并且始终需要使用特定级别进行身份验证的情况非常有用。

请注意,当登录请求从客户端通过用户浏览器发送到 Keycloak 时,URL 中的参数(例如 claimsacr_values)可能会被用户更改。如果客户端使用 PAR(推送授权请求)、请求对象或其他防止用户重写 URL 中参数的机制,则可以缓解这种情况。因此,在身份验证之后,建议客户端检查 ID Token 以仔细检查令牌中的 acr 是否与预期级别相符。

如果参数未显式请求级别,则 Keycloak 将要求使用身份验证流程中找到的第一个 LoA 条件进行身份验证,例如前面示例中的用户名/密码。当用户已经通过该级别身份验证并且该级别已过期时,用户不需要重新进行身份验证,但令牌中的 acr 值将为 0。此结果被视为仅基于 long-lived browser cookie 的身份验证,如 OIDC Core 1.0 规范的第 2 节中所述。

在用户的首次身份验证期间,始终执行第一个配置的带有 Conditional - Level Of Authentication 的子流程(无论请求的级别如何),因为用户尚没有任何级别。因此,我们建议第一个级别子流程包含用户身份验证所需的最低限度的身份验证器。此外,确保具有不同 Conditional - Level Of Authentication 值的子流程按从最低到最高的顺序排列,如上面的示例所示。例如,如果您配置了一个级别为 2 的子流程,然后添加了另一个级别为 1 的子流程,则在首次身份验证期间将始终询问级别为 2 的子流程,这可能不是期望的行为。
当管理员指定多个流程,为每个流程设置不同的 LoA 级别,并将这些流程分配给不同的客户端时,可能会出现冲突情况。但是,规则始终相同:如果用户具有某个级别,则只需要该级别即可连接到客户端。管理员有责任确保 LoA 是一致的。
具有身份验证级别条件的逐步身份验证适用于以下用例:每个级别都需要来自先前级别的所有身份验证方法。例如,级别 X 必须始终包含级别 X-1 所需的所有身份验证方法。对于特定级别(例如级别 3)需要与先前级别不同的身份验证方法的情况,使用 ACR 到特定流程的映射可能更合适。有关更多详细信息,请参阅使用客户端策略选择身份验证流程

示例场景

  1. 级别 1 条件的最大年龄配置为 300 秒。

  2. 发送登录请求,未请求任何 acr。将使用级别 1,用户需要使用用户名和密码进行身份验证。令牌将具有 acr=1

  3. 在 100 秒后发送另一个登录请求。由于 SSO,用户已自动通过身份验证,令牌将返回 acr=1

  4. 在另外 201 秒后(自第 2 点中的身份验证起 301 秒)发送另一个登录请求。由于 SSO,用户已自动通过身份验证,但由于级别 1 被视为已过期,令牌将返回 acr=0

  5. 发送另一个登录请求,但现在它将在 claims 参数中显式请求级别 1 的 ACR。将要求用户使用用户名/密码重新进行身份验证,然后令牌中将返回 acr=1

令牌中的 ACR 声明

ACR 声明由在 acr 客户端范围中定义的 acr loa level 协议映射器添加到令牌中。此客户端范围是 realm 默认客户端范围,因此将添加到 realm 中所有新创建的客户端。

如果您不希望令牌内部包含 acr 声明,或者您需要一些自定义逻辑来添加它,您可以从客户端中删除客户端范围。

请注意,当登录请求发起一个使用 claims 参数请求 acr 作为 essential 声明的请求时,Keycloak 将始终返回指定的级别之一。如果它无法返回指定的级别之一(例如,如果请求的级别未知或大于身份验证流程中配置的条件),则 Keycloak 将抛出错误。

客户端请求的注册或重置凭据

通常,当用户从客户端应用程序重定向到 Keycloak 时,会触发 browser 流程。如果 realm 注册已启用并且用户在登录屏幕上单击 Register,则此流程可能允许用户注册。此外,如果为 realm 启用了忘记密码,则用户可以单击登录屏幕上的 Forget password,这将触发 Reset credentials 流程,用户可以在电子邮件地址确认后重置凭据。

有时,客户端应用程序直接将用户重定向到 Registration 屏幕或 Reset credentials 流程可能很有用。结果操作将与用户在正常登录屏幕上单击 RegisterForget password 时的操作相匹配。可以按如下方式自动重定向到注册或重置凭据屏幕

  • 当客户端希望用户直接重定向到注册时,OIDC 客户端应将参数 prompt=create 添加到登录请求。作为已弃用的替代方法,客户端可以将 OIDC 登录 URL 路径 (/auth) 中的最后一个代码段替换为 /registrations。因此,完整的 URL 可能类似于以下内容:https://keycloak.example.com/realms/your_realm/protocol/openid-connect/registrations。建议使用 prompt=create,因为它是一个规范标准

  • 当客户端希望用户直接重定向到 Reset credentials 流程时,OIDC 客户端应将 OIDC 登录 URL 路径 (/auth) 中的最后一个代码段替换为 /forgot-credentials

上述步骤是客户端直接请求注册或重置凭据流程的唯一受支持方法。出于安全目的,不支持且不建议客户端应用程序绕过 OIDC/SAML 流程并直接重定向到其他 Keycloak 端点(例如 /realms/realm_name/login-actions/realms/realm_name/broker 下的端点)。

用户会话限制

可以配置用户可以拥有的会话数量的限制。会话可以按 realm 或按客户端进行限制。

要向流程添加会话限制,请执行以下步骤。

  1. 单击流程的 Add step

  2. 从项目列表中选择 User session count limiter

  3. 点击 添加

  4. 对于 User Session Count Limiter 身份验证类型,单击 Required 以将其要求设置为必需。

  5. 单击 User Session Count Limiter⚙️ (齿轮图标)。

  6. 输入此配置的别名。

  7. 输入用户可以在此 realm 中拥有的最大会话数。例如,如果值为 2,则每个用户可以在此 realm 中拥有的最大 SSO 会话数为 2。如果值为 0,则禁用此检查。

  8. 输入用户可以为客户端拥有的最大会话数。例如,如果值为 2,则每个客户端在此 realm 中最多可以有 2 个 SSO 会话。因此,当用户尝试向客户端 foo 进行身份验证时,但该用户已向客户端 foo 进行了 2 个 SSO 会话的身份验证,则将拒绝身份验证或根据配置的行为终止现有会话。如果使用值 0,则禁用此检查。如果同时启用了会话限制和客户端会话限制,则客户端会话限制始终低于会话限制是有意义的。每个客户端的限制永远不能超过此用户的所有 SSO 会话的限制。

  9. 选择当用户尝试在达到限制后创建会话时所需的行为。可用行为为

    • Deny new session - 当请求新会话且达到会话限制时,无法创建新会话。

    • Terminate oldest session - 当请求新会话且已达到会话限制时,将删除最旧的会话并创建新会话。

  10. (可选)添加在达到限制时要显示的自定义错误消息。

请注意,用户会话限制应添加到您绑定的 Browser flowDirect grant flowReset credentials 以及任何 Post broker login flow。身份验证器应在身份验证期间用户已知时添加(通常在身份验证流程结束时),并且通常应为 REQUIRED。请注意,在同一级别不可能同时具有 ALTERNATIVE 和 REQUIRED 执行。

对于大多数身份验证器(如 Direct grant flowReset credentialsPost broker login flow),建议在身份验证流程结束时将身份验证器添加为 REQUIRED。以下是 Reset credentials 流程的示例

Authentication User Session Limits Reset Credentials Flow

对于 Browser 流程,请考虑不要在顶层流程中添加会话限制身份验证器。此建议是由于 Cookie 身份验证器,它基于 SSO cookie 自动重新验证用户身份。它位于顶层,最好不要在 SSO 重新身份验证期间检查会话限制,因为用户会话已经存在。因此,请考虑添加一个单独的 ALTERNATIVE 子流程,例如与 Cookie 处于同一级别的以下 authenticate-user-with-session-limit 示例。然后,您可以添加一个 REQUIRED 子流程,在以下 real-authentication-subflow 示例中,作为 authenticate-user-with-session-limit 的嵌套子流程,并在同一级别添加 User Session Limit。在 real-authentication-subflow 内部,您可以以类似于默认浏览器流程的方式添加真正的身份验证器。以下示例流程允许用户使用身份提供程序或密码和 OTP 进行身份验证

Authentication User Session Limits Browser Flow

关于 Post Broker login flow,只要您没有在与身份提供程序进行身份验证后触发的其他身份验证器,您就可以在身份验证流程中添加 User Session Limits 作为唯一的身份验证器。但是,请确保此流程在您的身份提供程序中配置为 Post Broker Flow。需要此要求,以便与身份提供程序的身份验证也参与会话限制。

目前,管理员负责维护不同配置之间的一致性。因此,请确保您的所有流程都使用相同的 User Session Limits 配置。
用户会话限制功能不适用于 CIBA。

脚本身份验证器

通过管理控制台和 REST 端点上传脚本的功能已弃用。

更多详情请参阅 JavaScript 提供程序

Kerberos

Keycloak 支持通过简单且受保护的 GSSAPI 协商机制 (SPNEGO) 协议使用 Kerberos 票证登录。SPNEGO 在用户验证会话后通过 Web 浏览器透明地进行身份验证。对于非 Web 场景,或者当登录期间票证不可用时,Keycloak 支持使用 Kerberos 用户名和密码登录。

Web 身份验证的典型用例如下

  1. 用户登录到桌面。

  2. 用户使用浏览器访问由 Keycloak 保护的 Web 应用程序。

  3. 应用程序重定向到 Keycloak 登录。

  4. Keycloak 渲染 HTML 登录屏幕,状态码为 401,HTTP 标头为 WWW-Authenticate: Negotiate

  5. 如果浏览器具有来自桌面登录的 Kerberos 票证,则浏览器在标头 Authorization: Negotiate 'spnego-token' 中将桌面登录信息传输到 Keycloak。否则,它将显示标准登录屏幕,用户输入登录凭据。

  6. Keycloak 验证来自浏览器的令牌并验证用户身份。

  7. 如果将 LDAPFederationProvider 与 Kerberos 身份验证支持一起使用,Keycloak 会从 LDAP 预置用户数据。如果使用 KerberosFederationProvider,Keycloak 允许用户更新配置文件并预填充登录数据。

  8. Keycloak 返回到应用程序。Keycloak 和应用程序通过 OpenID Connect 或 SAML 消息进行通信。Keycloak 充当 Kerberos/SPNEGO 登录的代理。因此,通过 Kerberos 进行身份验证的 Keycloak 对应用程序是隐藏的。

Negotiate www-authenticate 方案允许 NTLM 作为 Kerberos 的后备方案,并且在某些 Windows Web 浏览器中默认支持 NTLM。如果 www-authenticate 质询来自浏览器允许列表之外的服务器,则用户可能会遇到 NTLM 对话框提示。用户需要单击对话框上的“取消”按钮才能继续,因为 Keycloak 不支持此机制。如果 Intranet Web 浏览器未严格配置,或者 Keycloak 同时为 Intranet 和 Internet 用户提供服务,则可能会发生这种情况。可以使用自定义身份验证器将 Negotiate 质询限制为主机白名单。

执行以下步骤来设置 Kerberos 身份验证

  1. Kerberos 服务器 (KDC) 的设置和配置。

  2. Keycloak 服务器的设置和配置。

  3. 客户端机器的设置和配置。

Kerberos 服务器的设置

设置 Kerberos 服务器的步骤取决于操作系统 (OS) 和 Kerberos 供应商。有关设置和配置 Kerberos 服务器的说明,请参阅 Windows Active Directory、MIT Kerberos 和您的操作系统文档。

在设置期间,执行以下步骤

  1. 向您的 Kerberos 数据库添加一些用户主体。您还可以将 Kerberos 与 LDAP 集成,以便从 LDAP 服务器预置用户帐户。

  2. 为“HTTP”服务添加服务主体。例如,如果 Keycloak 服务器在 www.mydomain.org 上运行,则添加服务主体 HTTP/www.mydomain.org@<kerberos realm>

    在 MIT Kerberos 上,您运行“kadmin”会话。在装有 MIT Kerberos 的机器上,您可以使用命令

sudo kadmin.local

然后,添加 HTTP 主体并使用如下命令将其密钥导出到 keytab 文件

addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG
ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG

确保 Keycloak 运行的主机可以访问 keytab 文件 /tmp/http.keytab

Keycloak 服务器的设置和配置

在您的机器上安装 Kerberos 客户端。

步骤
  1. 安装 Kerberos 客户端。如果您的机器运行 Fedora、Ubuntu 或 RHEL,请安装 freeipa-client 软件包,其中包含 Kerberos 客户端和其他实用程序。

  2. 配置 Kerberos 客户端(在 Linux 上,配置设置位于 /etc/krb5.conf 文件中)。

    将您的 Kerberos realm 添加到配置中,并配置您的服务器运行的 HTTP 域。

    例如,对于 MYDOMAIN.ORG realm,您可以像这样配置 domain_realm 部分

    [domain_realm]
      .mydomain.org = MYDOMAIN.ORG
      mydomain.org = MYDOMAIN.ORG
  3. 导出包含 HTTP 主体的 keytab 文件,并确保运行 Keycloak 服务器的进程可以访问该文件。对于生产环境,请确保只有此进程可以读取该文件。

    对于上面的 MIT Kerberos 示例,我们将 keytab 导出到 /tmp/http.keytab 文件。如果您的密钥分发中心 (KDC) 和 Keycloak 在同一主机上运行,则该文件已可用。

启用 SPNEGO 处理

默认情况下,Keycloak 禁用 SPNEGO 协议支持。要启用它,请转到浏览器流并启用Kerberos

浏览器流程

Browser Flow

Kerberos 要求从禁用设置为备选(Kerberos 是可选的)或必需(浏览器必须启用 Kerberos)。如果您尚未配置浏览器以使用 SPNEGO 或 Kerberos,则 Keycloak 将回退到常规登录屏幕。

配置 Kerberos 用户存储联合提供程序

您现在必须使用用户存储联合来配置 Keycloak 如何解释 Kerberos 票证。存在两个不同的具有 Kerberos 身份验证支持的联合提供程序。

要使用 LDAP 服务器支持的 Kerberos 进行身份验证,请配置 LDAP 联合提供程序

步骤
  1. 转到 LDAP 提供程序的配置页面。

    Ldap kerberos 集成

    LDAP Kerberos Integration

  2. 允许 Kerberos 身份验证切换为开启

允许 Kerberos 身份验证使 Keycloak 使用 Kerberos 主体访问用户信息,以便信息可以导入到 Keycloak 环境中。

如果 LDAP 服务器不支持您的 Kerberos 解决方案,请使用 Kerberos 用户存储联合提供程序。

步骤
  1. 单击菜单中的 User Federation(用户联合)。

  2. 添加提供程序选择框中选择 Kerberos

    Kerberos 用户存储提供程序

    Kerberos User Storage Provider

Kerberos 提供程序解析 Kerberos 票证以获取简单的主体信息,并将信息导入到本地 Keycloak 数据库。用户配置文件信息(如名字、姓氏和电子邮件)未预置。

客户端机器的设置和配置

客户端机器必须具有 Kerberos 客户端,并按照上述说明设置 krb5.conf。客户端机器还必须在其浏览器中启用 SPNEGO 登录支持。如果您正在使用 Firefox 浏览器,请参阅配置 Firefox 以使用 Kerberos

.mydomain.org URI 必须在 network.negotiate-auth.trusted-uris 配置选项中。

在 Windows 域中,客户端无需调整其配置。Internet Explorer 和 Edge 已经可以参与 SPNEGO 身份验证。

示例设置

Keycloak 和 FreeIPA Docker 镜像

当您安装 docker 时,运行一个安装了 FreeIPA 服务器的 Docker 镜像。FreeIPA 提供了一个集成的安全解决方案,包含 MIT Kerberos 和 389 LDAP 服务器。该镜像还包含一个配置了 LDAP 联合提供程序并针对 FreeIPA 服务器启用了 SPNEGO/Kerberos 身份验证的 Keycloak 服务器。有关详细信息,请参阅此处

ApacheDS 测试 Kerberos 服务器

对于快速测试和单元测试,请使用简单的 ApacheDS Kerberos 服务器。您必须从源代码构建 Keycloak,然后使用 maven-exec-plugin 从我们的测试套件运行 Kerberos 服务器。有关详细信息,请参阅此处

凭据委派

Kerberos 支持凭据委派。应用程序可能需要访问 Kerberos 票证,以便它们可以重用它来与受 Kerberos 保护的其他服务进行交互。由于 Keycloak 服务器处理了 SPNEGO 协议,您必须在 OpenID Connect 令牌声明或 SAML 断言属性中将 GSS 凭据传播到您的应用程序。Keycloak 从 Keycloak 服务器将此传输到您的应用程序。要将此声明插入到令牌或断言中,每个应用程序都必须启用内置协议映射器 gss delegation credential。此映射器在应用程序客户端页面的映射器选项卡中可用。有关更多详细信息,请参阅协议映射器章节。

应用程序必须反序列化它从 Keycloak 接收的声明,然后才能使用它对其他服务进行 GSS 调用。当您从访问令牌反序列化凭据到 GSSCredential 对象时,请创建 GSSContext,并将此凭据传递给 GSSManager.createContext 方法。例如

// Obtain accessToken in your application.
KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) servletReq.getUserPrincipal();
AccessToken accessToken = keycloakPrincipal.getKeycloakSecurityContext().getToken();

// Retrieve Kerberos credential from accessToken and deserialize it
String serializedGssCredential = (String) accessToken.getOtherClaims().
    get(org.keycloak.common.constants.KerberosConstants.GSS_DELEGATION_CREDENTIAL);

GSSCredential deserializedGssCredential = org.keycloak.common.util.KerberosSerializationUtils.
    deserializeCredential(serializedGssCredential);

// Create GSSContext to call other Kerberos-secured services
GSSContext context = gssManager.createContext(serviceName, krb5Oid,
    deserializedGssCredential, GSSContext.DEFAULT_LIFETIME);

krb5.conf 文件中配置 forwardable Kerberos 票证,并为您的浏览器添加对委派凭据的支持。

凭据委派具有安全隐患,因此仅在必要时且仅在 HTTPS 的情况下使用它。有关更多详细信息和示例,请参阅本文

跨 realm 信任

在 Kerberos 协议中,realm 是一组 Kerberos 主体。这些主体的定义存在于 Kerberos 数据库中,该数据库通常是 LDAP 服务器。

Kerberos 协议允许跨 realm 信任。例如,如果存在 2 个 Kerberos realm A 和 B,则跨 realm 信任将允许 realm A 中的用户访问 realm B 的资源。Realm B 信任 realm A。

Kerberos 跨 realm 信任

kerberos trust basic

Keycloak 服务器支持跨 realm 信任。要实现此目的,请执行以下操作

  • 为跨 realm 信任配置 Kerberos 服务器。实现此步骤取决于 Kerberos 服务器实现。此步骤对于将 Kerberos 主体 krbtgt/B@A 添加到 realm A 和 B 的 Kerberos 数据库是必要的。此主体在两个 Kerberos realm 上必须具有相同的密钥。主体在两个 realm 中必须具有相同的密码、密钥版本号和密码。有关更多详细信息,请参阅 Kerberos 服务器文档。

跨 realm 信任默认是单向的。您必须将主体 krbtgt/A@B 添加到两个 Kerberos 数据库,以实现 realm A 和 realm B 之间的双向信任。但是,信任默认是可传递的。如果 realm B 信任 realm A,并且 realm C 信任 realm B,则 realm C 信任 realm A,而无需主体 krbtgt/C@A 可用。客户端可能需要额外的配置(例如,capaths),以便客户端可以找到信任路径。有关更多详细信息,请参阅 Kerberos 文档。

  • 配置 Keycloak 服务器

    • 当使用支持 Kerberos 的 LDAP 存储提供程序时,配置 realm B 的服务器主体,如本例所示:HTTP/mydomain.com@B。LDAP 服务器必须找到 realm A 中的用户(如果 realm A 中的用户要成功地向 Keycloak 进行身份验证),因为 Keycloak 必须执行 SPNEGO 流,然后找到用户。

查找用户基于 LDAP 存储提供程序选项 Kerberos principal attribute。例如,如果将其配置为 userPrincipalName 之类的值,则在用户 john@A 的 SPNEGO 身份验证之后,Keycloak 将尝试查找属性 userPrincipalName 等于 john@A 的 LDAP 用户。如果 Kerberos principal attribute 留空,则 Keycloak 将基于其 Kerberos 主体的前缀(省略 realm)查找 LDAP 用户。例如,Kerberos 主体用户 john@A 必须在 LDAP 中以用户名 john 可用,因此通常在 LDAP DN 下,例如 uid=john,ou=People,dc=example,dc=com。如果您希望 realm A 和 B 中的用户进行身份验证,请确保 LDAP 可以找到来自 realm A 和 B 的用户。

  • 当使用 Kerberos 用户存储提供程序(通常,没有 LDAP 集成的 Kerberos)时,将服务器主体配置为 HTTP/mydomain.com@B,并且来自 Kerberos realm A 和 B 的用户必须能够进行身份验证。

允许多个 Kerberos realm 中的用户进行身份验证,因为每个用户都将具有属性 KERBEROS_PRINCIPAL,该属性引用用于身份验证的 Kerberos 主体,并且这用于进一步查找此用户。为避免当 Kerberos realm AB 中都有用户 john 时发生冲突,Keycloak 用户的用户名可能包含 Kerberos realm(小写)。例如,用户名将是 john@a。以防万一 realm 与配置的 Kerberos realm 匹配,realm 后缀可能会从生成的用户名中省略。例如,对于 Kerberos 主体 john@A,用户名将是 john,只要 Kerberos realm 在 Kerberos 提供程序上配置为 A 即可。

故障排除

如果您遇到问题,请启用其他日志记录来调试问题

  • 在管理控制台中为 Kerberos 或 LDAP 联合提供程序启用 Debug 标志

  • 为类别 org.keycloak 启用 TRACE 日志记录以在服务器日志中接收更多信息

  • 添加系统属性 -Dsun.security.krb5.debug=true-Dsun.security.spnego.debug=true

X.509 客户端证书用户身份验证

如果您已将服务器配置为使用 mutual SSL 身份验证,则 Keycloak 支持使用 X.509 客户端证书登录。

典型工作流程

  • 客户端通过 SSL/TLS 通道发送身份验证请求。

  • 在 SSL/TLS 握手期间,服务器和客户端交换其 x.509/v3 证书。

  • 容器 (WildFly) 验证证书 PKIX 路径和证书到期日期。

  • x.509 客户端证书身份验证器通过使用以下方法来验证客户端证书

    • 通过使用 CRL 或 CRL 分发点检查证书吊销状态。

    • 通过使用 OCSP(在线证书状态协议)检查证书吊销状态。

    • 验证证书中的密钥是否与预期密钥匹配。

    • 验证证书中的扩展密钥是否与预期的扩展密钥匹配。

  • 如果这些检查中的任何一项失败,则 x.509 身份验证失败。否则,身份验证器将提取证书身份并将其映射到现有用户。

当证书映射到现有用户时,行为会根据身份验证流而有所不同

  • 在浏览器流中,服务器提示用户确认其身份或使用用户名和密码登录。

  • 在直接授权流中,服务器登录用户。

请注意,验证证书 PKIX 路径是 Web 容器的责任。Keycloak 端的 X.509 身份验证器仅提供额外的支持来检查证书过期时间、证书吊销状态和密钥用途。如果您正在使用部署在反向代理后面的 Keycloak,请确保您的反向代理配置为验证 PKIX 路径。如果您不使用反向代理,并且用户直接访问 WildFly,那么您应该没问题,因为只要按照以下描述进行配置,WildFly 就会确保 PKIX 路径得到验证。

功能

支持的证书身份来源

  • 使用正则表达式匹配 SubjectDN

  • X500 主题的电子邮件属性

  • 来自主题备用名称扩展(RFC822Name 通用名称)的 X500 主题电子邮件

  • 来自主题备用名称扩展的 X500 主题的其他名称。此其他名称通常是用户主体名称 (UPN)。

  • X500 主题的通用名称属性

  • 使用正则表达式匹配颁发者 DN

  • 证书序列号

  • 证书序列号和颁发者 DN

  • SHA-256 证书指纹

  • PEM 格式的完整证书

正则表达式

Keycloak 通过使用正则表达式作为过滤器,从主题 DN 或颁发者 DN 中提取证书身份。例如,以下正则表达式匹配电子邮件属性

emailAddress=(.*?)(?:,|$)

如果将“身份来源”设置为“使用正则表达式匹配 SubjectDN”或“使用正则表达式匹配颁发者 DN”,则应用正则表达式过滤。

将证书身份映射到现有用户

证书身份映射可以将提取的用户身份映射到现有用户的用户名、电子邮件或与证书身份匹配的自定义属性值。例如,将“身份来源”设置为主题的电子邮件或将“用户映射方法”设置为用户名或电子邮件,会使 X.509 客户端证书身份验证器使用证书主题 DN 中的电子邮件属性作为搜索条件,以便通过用户名或电子邮件搜索现有用户。

  • 如果您在领域设置中禁用使用电子邮件登录,则相同的规则适用于证书身份验证。用户将无法使用电子邮件属性登录。

  • 使用“证书序列号和颁发者 DN”作为身份来源需要两个自定义属性,分别用于序列号和颁发者 DN。

  • SHA-256 证书指纹”是 SHA-256 证书指纹的小写十六进制表示形式。

  • 使用“PEM 格式的完整证书”作为身份来源仅限于映射到外部联合来源(例如 LDAP)的自定义属性。由于长度限制,Keycloak 无法在其数据库中存储证书,因此在 LDAP 的情况下,您必须启用“始终从 LDAP 读取值”。

扩展证书验证
  • 使用 CRL 检查吊销状态。

  • 使用 CRL/分发点检查吊销状态。

  • 使用 OCSP/响应者 URI 检查吊销状态。

  • 证书密钥用途验证。

  • 证书扩展密钥用途验证。

将 X.509 客户端证书身份验证添加到浏览器流程

  1. 点击菜单中的 身份验证

  2. 单击浏览器流程。

  3. 操作列表中,选择复制

  4. 输入副本的名称。

  5. 单击复制

  6. 点击 添加步骤

  7. 单击“X509/验证用户名表单”。

  8. 点击 添加

    X509 执行

    X509 Execution

  9. 单击并将“X509/验证用户名表单”拖到“浏览器表单”执行之上。

  10. 将要求设置为“备选”。

    X509 浏览器流程

    X509 Browser Flow

  11. 单击操作菜单。

  12. 单击绑定流程

  13. 从下拉列表中单击浏览器流程

  14. 点击 保存

    X509 浏览器流程绑定

    X509 Browser Flow Bindings

配置 X.509 客户端证书身份验证

X509 配置

X509 Configuration

用户身份来源

定义从客户端证书中提取用户身份的方法。

启用规范 DN 表示

定义是否使用规范格式来确定专有名称。官方 Java API 文档描述了该格式。此选项仅影响两个用户身份来源:使用正则表达式匹配 SubjectDN使用正则表达式匹配颁发者 DN。当您设置新的 Keycloak 实例时,启用此选项。禁用此选项以保留与现有 Keycloak 实例的向后兼容性。

启用序列号十六进制表示

序列号表示为十六进制。符号位设置为 1 的序列号必须使用 00 八位字节进行左填充。例如,根据 RFC5280,十进制值161或十六进制表示形式a1的序列号编码为 00a1。有关更多详细信息,请参见 RFC5280,附录 B

正则表达式

用作过滤器以提取证书身份的正则表达式。表达式必须包含单个组。

用户映射方法

定义将证书身份与现有用户匹配的方法。用户名或电子邮件通过用户名或电子邮件搜索现有用户。自定义属性映射器搜索具有与证书身份匹配的自定义属性的现有用户。自定义属性的名称是可配置的。

用户属性名称

其值与证书身份匹配的自定义属性。当属性映射与多个值相关时,请使用多个自定义属性。例如,“证书序列号和颁发者 DN”。

启用 CRL 检查

通过使用证书吊销列表检查证书的吊销状态。列表的位置在CRL 文件路径属性中定义。

启用 CRL 分发点以检查证书吊销状态

使用 CDP 检查证书吊销状态。大多数 PKI 机构在其证书中包含 CDP。

CRL 文件路径

包含 CRL 列表的文件的路径。如果启用了启用 CRL 检查选项,则该值必须是有效文件的路径。

CRL 如果未更新则中止

符合 RFC5280 的 CRL 包含一个下次更新字段,该字段指示将发布下一个 CRL 的日期。当该时间过去后,CRL 被认为已过时,应刷新。如果此选项为 true,则如果 CRL 过时,身份验证将失败(推荐)。如果该选项设置为 false,则仍使用过时的 CRL 来验证用户证书。

启用 OCSP 检查

通过使用在线证书状态协议检查证书吊销状态。

OCSP 故障开放行为

默认情况下,OCSP 检查必须返回肯定响应才能继续进行成功的身份验证。但是,有时此检查可能是不确定的:例如,OCSP 服务器可能无法访问、过载,或者客户端证书可能不包含 OCSP 响应者 URI。当此设置打开时,仅当 OCSP 响应者收到明确的否定响应并且证书确实被吊销时,才会拒绝身份验证。如果有效的 OCSP 响应不可用,则将接受身份验证尝试。

OCSP 响应者 URI

覆盖证书中 OCSP 响应者 URI 的值。

验证密钥用途

验证是否设置了证书的 KeyUsage 扩展位。例如,“digitalSignature,KeyEncipherment”验证 KeyUsage 扩展中的位 0 和位 2 是否已设置。将此参数留空以禁用密钥用途验证。有关更多信息,请参见 RFC5280,第 4.2.1.3 节。当密钥用途不匹配时,Keycloak 会引发错误。

验证扩展密钥用途

验证扩展密钥用途扩展中定义的一个或多个用途。有关更多信息,请参见 RFC5280,第 4.2.1.12 节。将此参数留空以禁用扩展密钥用途验证。当颁发 CA 标记为关键且发生密钥用途扩展不匹配时,Keycloak 会引发错误。

验证证书策略

验证证书策略扩展中定义的一个或多个策略 OID。请参见 RFC5280,第 4.2.1.4 节。将参数留空以禁用证书策略验证。多个策略应使用逗号分隔。

证书策略验证模式

当在“验证证书策略”设置中指定多个策略时,它决定匹配应检查所有请求的策略都存在,还是一个匹配足以进行成功的身份验证。默认值为 全部,表示客户端证书中应存在所有请求的策略。

绕过身份确认

如果启用,X.509 客户端证书身份验证不会提示用户确认证书身份。Keycloak 在成功身份验证后让用户登录。

重新验证客户端证书

如果设置,客户端证书信任链将始终在应用程序级别使用配置的信任存储区中存在的证书进行验证。如果底层 Web 服务器不强制执行客户端证书链验证,例如因为它位于非验证负载均衡器或反向代理之后,或者当允许的 CA 数量对于相互 SSL 协商来说太大时(大多数浏览器将最大 SSL 协商数据包大小限制为 32767 字节,这大约对应于 200 个通告的 CA),这可能很有用。默认情况下,此选项处于关闭状态。

将 X.509 客户端证书身份验证添加到直接授权流程

  1. 点击菜单中的 身份验证

  2. 从“操作列表”中选择复制以制作内置“直接授权”流程的副本。

  3. 输入副本的名称。

  4. 单击复制

  5. 单击创建的流程。

  6. 单击“用户名验证”的垃圾桶图标 🗑️,然后单击删除

  7. 单击“密码”的垃圾桶图标 🗑️,然后单击删除

  8. 点击 添加步骤

  9. 单击“X509/验证用户名”。

  10. 点击 添加

    X509 直接授权执行

    X509 Direct Grant Execution

  11. 按照 x509 浏览器流程 部分中描述的步骤设置 x509 身份验证配置。

  12. 单击绑定选项卡。

  13. 单击直接授权流程下拉列表。

  14. 单击新创建的“x509 直接授权”流程。

  15. 点击 保存

    X509 直接授权流程绑定

    X509 Direct Grant Flow Bindings

使用 CURL 的示例

以下示例演示如何使用直接授权流程为 realm test 中的用户获取访问令牌。该示例在 保护应用程序 部分中使用 OAuth2 资源所有者密码凭据授权和机密客户端 resource-owner

curl \
  -d "client_id=resource-owner" \
  -d "client_secret=40cc097b-2a57-4c17-b36a-8fdf3fc2d578" \
  -d "grant_type=password" \
  --cacert /tmp/truststore.pem \
  --cert /tmp/keystore.pem:kssecret \
  "https://#:8543/realms/test/protocol/openid-connect/token"

文件 /tmp/truststore.pem 指向包含 Keycloak 服务器证书的信任存储区的文件。文件 /tmp/keystore.pem 包含与 Keycloak 用户对应的私钥和证书,该用户将通过此请求成功进行身份验证。这取决于身份验证器配置如何将证书中的内容映射到 Keycloak 用户,如 配置部分中所述。kssecret 可能是此密钥库文件的密码。

根据您的环境,可能需要使用更多 CURL 命令选项,例如

  • 如果您使用自签名证书,则使用选项 --insecure

  • 使用选项 --capath 以包含包含证书颁发机构路径的整个目录

  • 如果您想使用与 PEM 不同的文件,则使用选项 --cert-type--key-type

如果需要,请查阅 curl 工具的文档以获取详细信息。如果您使用 curl 以外的其他工具,请查阅您的工具的文档。但是,设置将是类似的。如果使用机密客户端,则需要包含密钥库和信任存储区以及客户端凭据。

如果可能,最好将 服务帐户 与 MTLS 客户端身份验证(客户端身份验证器 X509 证书)结合使用,而不是使用带有 X.509 身份验证的直接授权,因为直接授权可能需要与客户端应用程序共享用户证书。使用服务帐户时,令牌是以客户端自身的名义获取的,这通常是更好、更安全的做法。

W3C Web 身份验证 (WebAuthn)

Keycloak 提供对 W3C Web 身份验证 (WebAuthn) 的支持。Keycloak 作为 WebAuthn 的 依赖方 (RP) 工作。

WebAuthn 的操作成功取决于用户的 WebAuthn 支持的身份验证器、浏览器和平台。请确保您的身份验证器、浏览器和平台支持 WebAuthn 规范。

WebAuthn 的规范使用 user.id 将公钥凭据映射到依赖方中的特定用户帐户。此用户 ID 句柄是一个不透明的字节序列,最大大小为 64 字节。Keycloak 将内部数据库 ID 传递给注册,在普通用户中,这是一个 36 个字符的 UUID。但是,如果用户来自外部用户联合提供程序,则内部 Keycloak ID 是 存储 ID,格式为 f:<provider-id>:<user-id>,可以超过 64 字节的限制。将 Storage SPI 和 WebAuthn 结合使用时,请考虑这一点,并为联合提供程序组件和来自该提供程序的用户使用短 ID。

设置

WebAuthn 支持 2FA 的设置过程如下

启用 WebAuthn 身份验证器注册
  1. 点击菜单中的 身份验证

  2. 点击 Required Actions(必需的操作) 选项卡。

  3. Webauthn Register 开关切换到 开启

如果您希望所有新用户都需要注册其 WebAuthn 凭据,请将 Default Action 开关切换到 开启

向浏览器流添加 WebAuthn 身份验证

  1. 点击菜单中的 身份验证

  2. 单击浏览器流程。

  3. 从“Action list”中选择 Duplicate 以创建内置 Browser 流的副本。

  4. 输入 “WebAuthn Browser” 作为副本的名称。

  5. 单击复制

  6. 单击名称以转到详细信息

  7. 单击 “WebAuthn Browser Browser - Conditional OTP” 的垃圾桶图标 🗑️,然后单击 Delete

如果您需要所有用户都使用 WebAuthn

  1. 单击 **WebAuthn Browser Forms** 的 **+** 菜单。

  2. 点击 添加步骤

  3. 单击 **WebAuthn Authenticator**。

  4. 点击 添加

  5. WebAuthn Authenticator 身份验证类型选择 Required,以将其要求设置为必需。

    Webauthn browser flow required

  6. 点击屏幕顶部的 操作 菜单。

  7. 从下拉列表中选择 Bind flow

  8. 从下拉列表中选择 Browser

  9. 点击 保存

如果用户没有 WebAuthn 凭据,则用户必须注册 WebAuthn 凭据。

用户只能在注册了 WebAuthn 凭据后才能使用 WebAuthn 登录。因此,您可以不用添加 WebAuthn Authenticator 执行,而是

步骤
  1. 单击 **WebAuthn Browser Forms** 行的 **+** 菜单。

  2. 点击 添加子流程

  3. 在 *name* 字段中输入 “Conditional 2FA”。

  4. Conditional 2FA 选择 Conditional,以将其要求设置为有条件。

  5. 在 **Conditional 2FA** 行中,单击加号 + 并选择 **Add condition**。

  6. 点击 添加条件

  7. 选择 **Condition - User Configured**。

  8. 点击 添加

  9. Condition - User Configured 选择 Required,以将其要求设置为必需。

  10. WebAuthn Authenticator 拖放到 **Conditional 2FA** 流中

  11. WebAuthn Authenticator 选择 Alternative,以将其要求设置为备选。

    Webauthn browser flow conditional

用户可以选择使用 WebAuthn 或 OTP 作为第二因素

步骤
  1. 在 **Conditional 2FA** 行中,单击加号 + 并选择 **Add step**。

  2. 从列表中选择 OTP 表单

  3. 点击 添加

  4. 为 **OTP Form** 选择 Alternative,以将其要求设置为备选。

    WebAuthn browser flow conditional with OTP

使用 WebAuthn 身份验证器进行身份验证

注册 WebAuthn 身份验证器后,用户执行以下操作

  • 打开登录表单。用户必须使用用户名和密码进行身份验证。

  • 用户的浏览器会要求用户使用其 WebAuthn 身份验证器进行身份验证。

以管理员身份管理 WebAuthn

管理凭据

Keycloak 管理 WebAuthn 凭据的方式与其他凭据类似,请参阅 用户凭据管理

  • Keycloak 为用户分配一个必需的操作,以从 **Reset Actions** 列表中创建 WebAuthn 凭据,并选择 **Webauthn Register**。

  • 管理员可以通过单击 **Delete** 来删除 WebAuthn 凭据。

  • 管理员可以通过选择 **Show data…​** 来查看凭据的数据,例如 AAGUID。

  • 管理员可以通过在 **User Label** 字段中设置值并保存数据来为凭据设置标签。

管理策略

管理员可以为每个 realm 配置与 WebAuthn 相关的操作作为 **WebAuthn Policy**。

步骤
  1. 点击菜单中的 身份验证

  2. 点击 策略 (Policy) 选项卡。

  3. 单击 **WebAuthn Policy** 选项卡。

  4. 配置策略中的项目(请参阅以下描述)。

  5. 点击 保存

可配置的项目及其描述如下

配置 描述

Relying Party 实体名称

作为 WebAuthn Relying Party 的可读服务器名称。此项为必填项,适用于 WebAuthn 身份验证器的注册。默认设置为 “keycloak”。有关更多详细信息,请参阅 WebAuthn 规范

签名算法

告知 WebAuthn 身份验证器要用于 公钥凭据 的签名算法的算法。Keycloak 使用公钥凭据来签名和验证 身份验证断言。如果不存在算法,则采用默认的 ES256RS256。ES256 和 RS256 是一个可选配置项,适用于 WebAuthn 身份验证器的注册。有关更多详细信息,请参阅 WebAuthn 规范

Relying Party ID

WebAuthn Relying Party 的 ID,它确定 公钥凭据 的范围。ID 必须是源的有效域。此 ID 是一个可选配置项,应用于 WebAuthn 身份验证器的注册。如果此条目为空,则 Keycloak 会采用 Keycloak 基本 URL 的主机部分。有关更多详细信息,请参阅 WebAuthn 规范

证明传输偏好

浏览器上的 WebAuthn API 实现 (WebAuthn 客户端) 是生成证明语句的首选方法。此偏好是一个可选配置项,适用于 WebAuthn 身份验证器的注册。如果不存在选项,则其行为与选择 “none” 相同。有关更多详细信息,请参阅 WebAuthn 规范

身份验证器附件

WebAuthn 身份验证器对于 WebAuthn 客户端的可接受附件模式。此模式是一个可选配置项,适用于 WebAuthn 身份验证器的注册。有关更多详细信息,请参阅 WebAuthn 规范

要求可发现的凭据

要求 WebAuthn 身份验证器将公钥凭据生成为 客户端可发现的凭据 的选项。此选项适用于 WebAuthn 身份验证器的注册。如果留空,则其行为与选择 “No” 相同。有关更多详细信息,请参阅 WebAuthn 规范

用户验证要求

要求 WebAuthn 身份验证器确认用户验证的选项。这是一个可选配置项,适用于 WebAuthn 身份验证器的注册以及用户通过 WebAuthn 身份验证器的身份验证。如果不存在选项,则其行为与选择 “preferred” 相同。有关更多详细信息,请参阅 用于注册 WebAuthn 身份验证器的 WebAuthn 规范用于通过 WebAuthn 身份验证器验证用户的 WebAuthn 规范

超时

注册 WebAuthn 身份验证器和使用 WebAuthn 身份验证器验证用户的超时值(以秒为单位)。如果设置为零,则其行为取决于 WebAuthn 身份验证器的实现。默认值为 0。有关更多详细信息,请参阅 用于注册 WebAuthn 身份验证器的 WebAuthn 规范用于通过 WebAuthn 身份验证器验证用户的 WebAuthn 规范

避免相同身份验证器注册

如果启用,Keycloak 无法重新注册已注册的 WebAuthn 身份验证器。

可接受的 AAGUID

WebAuthn 身份验证器必须针对其注册的 AAGUID 白名单。

证明语句验证

注册 WebAuthn 身份验证器时,Keycloak 会验证 WebAuthn 身份验证器生成的证明语句的可信度。Keycloak 要求将信任锚的证书导入到 信任库 中。

要省略此验证,请禁用此信任库或将 WebAuthn 策略的配置项 “Attestation Conveyance Preference” 设置为 “none”。

以用户身份管理 WebAuthn 凭据

注册 WebAuthn 身份验证器

注册 WebAuthn 身份验证器的适当方法取决于用户是否已在 Keycloak 上注册帐户。

新用户

如果 realm 中的 **WebAuthn Register** 必需操作是 **Default Action**,则新用户必须在首次登录后设置 Passkey。

步骤
  1. 打开登录表单。

  2. 点击 注册

  3. 填写表单上的项目。

  4. 点击 注册

成功注册后,浏览器会要求用户输入其 WebAuthn 身份验证器标签的文本。

现有用户

如果 WebAuthn Authenticator 设置为必需,如第一个示例所示,则当现有用户尝试登录时,系统会自动要求他们注册其 WebAuthn 身份验证器

步骤
  1. 打开登录表单。

  2. 输入表单上的项目。

  3. 点击 保存

  4. 单击 **Login**。

成功注册后,用户的浏览器会要求用户输入其 WebAuthn 身份验证器标签的文本。

无密码 WebAuthn 与双因素身份验证结合使用

Keycloak 使用 WebAuthn 进行双因素身份验证,但您可以将 WebAuthn 用作第一因素身份验证。在这种情况下,具有 passwordless WebAuthn 凭据的用户无需密码即可向 Keycloak 进行身份验证。在 realm 和单个身份验证流的上下文中,Keycloak 可以将 WebAuthn 用作无密码和双因素身份验证机制。

管理员通常要求用户为 WebAuthn 无密码身份验证注册的 Passkey 满足不同的要求。例如,Passkey 可能要求用户使用 PIN 码向 Passkey 进行身份验证,或者 Passkey 使用更强的证书颁发机构进行证明。

因此,Keycloak 允许管理员配置单独的 WebAuthn Passwordless Policy。存在类型为必需的 Webauthn Register Passwordless 操作和类型为 WebAuthn Passwordless Authenticator 的单独身份验证器。

设置

按照以下步骤设置 WebAuthn 无密码支持

  1. (如果尚不存在)注册一个新的必需操作以支持 WebAuthn 无密码。使用 启用 WebAuthn 身份验证器注册 中描述的步骤。注册 Webauthn Register Passwordless 操作。

  2. 配置策略。您可以使用 管理策略 中描述的步骤和配置选项。在管理控制台的 **WebAuthn Passwordless Policy** 选项卡中执行配置。通常,Passkey 的要求将比双因素策略的要求更高。例如,在配置无密码策略时,您可以将 **User Verification Requirement** 设置为 **Required**。

  3. 配置身份验证流。使用 向浏览器流添加 WebAuthn 身份验证 中描述的 **WebAuthn Browser** 流。按如下方式配置流

    • **WebAuthn Browser Forms** 子流包含 **Username Form** 作为第一个身份验证器。删除默认的 **Username Password Form** 身份验证器,并添加 **Username Form** 身份验证器。此操作要求用户提供用户名作为第一步。

    • 将会有一个必需的子流,例如可以命名为 **Passwordless Or Two-factor**。此子流指示用户可以使用无密码 WebAuthn 凭据或双因素身份验证进行身份验证。

    • 该流包含 **WebAuthn Passwordless Authenticator** 作为第一个备选项。

    • 第二个备选项将是一个名为 **Password And Two-factor Webauthn** 的子流,例如。此子流包含 **Password Form** 和 **WebAuthn Authenticator**。

流的最终配置类似于此

无密码流

PasswordLess flow

现在,您可以将 **WebAuthn Register Passwordless** 作为必需操作添加到 Keycloak 中已知的用户,以进行测试。在首次身份验证期间,用户必须使用密码和第二因素 WebAuthn 凭据。如果用户使用 WebAuthn 无密码凭据,则无需提供密码和第二因素 WebAuthn 凭据。

无登录 WebAuthn

Keycloak 使用 WebAuthn 进行双因素身份验证,但您可以将 WebAuthn 用作第一因素身份验证。在这种情况下,具有 passwordless WebAuthn 凭据的用户无需提交登录名或密码即可向 Keycloak 进行身份验证。在 realm 的上下文中,Keycloak 可以将 WebAuthn 用作无登录/无密码和双因素身份验证机制。

管理员通常要求用户为 WebAuthn 无登录身份验证注册的 Passkey 满足不同的要求。无登录身份验证要求用户向 Passkey 进行身份验证(例如,使用 PIN 码或指纹),并且与无登录凭据关联的加密密钥物理存储在 Passkey 上。并非所有 Passkey 都满足这种要求。请咨询您的 Passkey 供应商,以了解您的设备是否支持“用户验证”和“可发现的凭据”。请参阅 受支持的 Passkey

Keycloak 允许管理员以允许无登录身份验证的方式配置 WebAuthn Passwordless Policy。请注意,无登录身份验证只能通过 WebAuthn Passwordless PolicyWebAuthn Passwordless 凭据进行配置。WebAuthn 无登录身份验证和 WebAuthn 无密码身份验证可以在同一 realm 上配置,但将共享相同的策略 WebAuthn Passwordless Policy

设置
步骤

按照以下步骤设置 WebAuthn 无登录支持

  1. (如果尚不存在)注册一个新的必需操作以支持 WebAuthn 无密码。使用 启用 WebAuthn 身份验证器注册 中描述的步骤。注册 Webauthn Register Passwordless 操作。

  2. 配置 WebAuthn Passwordless Policy。在管理控制台的 Authentication 部分中的 PoliciesWebAuthn Passwordless Policy 选项卡中执行配置。当您为无登录场景配置策略时,必须将 **User Verification Requirement** 设置为 **required**,并将 **Require Discoverable Credential** 设置为 **Yes**。请注意,由于没有专门的无登录策略,因此无法将用户验证=否/可发现凭据=否的身份验证场景与无登录场景(用户验证=是/可发现凭据=是)混合使用。Passkey 上的存储容量通常非常有限,这意味着您无法在 Passkey 上存储许多可发现的凭据。

  3. 配置身份验证流。创建一个新的身份验证流,添加 “WebAuthn Passwordless” 执行,并将执行的 Requirement 设置设置为 **Required**

流的最终配置类似于此

无登录流

LoginLess flow

现在,您可以将必需的操作 WebAuthn Register Passwordless 添加到 Keycloak 中已知的用户,以进行测试。配置了必需操作的用户将必须进行身份验证(例如,使用用户名/密码),然后系统将提示他们注册一个 Passkey,用于无登录身份验证。

供应商特定备注
兼容性检查清单

与 Keycloak 进行无登录身份验证需要 Passkey 满足以下功能

  • FIDO2 兼容性:不要与 FIDO/U2F 混淆

  • 用户验证:Passkey 验证用户的能力(防止有人找到您的 Passkey 并能够进行无登录和无密码身份验证)

  • 可发现的凭据:Passkey 存储登录名和与客户端应用程序关联的加密密钥的能力

Windows Hello

要使用基于 Windows Hello 的凭据向 Keycloak 进行身份验证,请将 WebAuthn Passwordless Policy 的 **Signature Algorithms** 设置配置为包括 **RS256** 值。请注意,某些浏览器不允许在私有窗口内访问平台 Passkey(如 Windows Hello)。

受支持的 Passkey

以下 Passkey 已成功通过 Keycloak 的无登录身份验证测试

  • Windows Hello (Windows 10 21H1/21H2)

  • Yubico Yubikey 5 NFC

  • Feitian ePass FIDO-NFC

Passkeys

Keycloak 提供了对 Passkeys 的预览支持。Keycloak 充当 Passkeys 依赖方 (RP)。

Passkey 注册和身份验证通过 WebAuthn 的功能实现。因此,Keycloak 的用户可以通过现有的 WebAuthn 注册和身份验证 来进行 Passkey 注册和身份验证。

同步 Passkeys 和设备绑定 Passkeys 都可以用于同设备和跨设备身份验证 (CDA)。但是,Passkeys 操作的成功与否取决于用户的环境。请确保在 该环境 中哪些操作可以成功。

使用条件 UI 的 Passkey 身份验证

使用条件 UI 的 Passkey 身份验证可以像 LoginLess WebAuthn 中一样,使用用户的 passkey 进行身份验证。此身份验证会向用户显示设备上存储的 passkey 列表,用户在该设备上运行浏览器。因此,用户可以选择列表中的一个 passkey 来进行身份验证。与 LoginLess WebAuthn 相比,此身份验证改善了用户的身份验证体验。

此身份验证使用 WebAuthn 条件 UI。因此,此身份验证的成功与否取决于用户的环境。如果环境不支持 WebAuthn 条件 UI,则此身份验证将回退到 LoginLess WebAuthn

Passkey 身份验证是 预览版,尚未完全支持。此功能默认情况下处于禁用状态。

要启用,请使用 --features=preview--features=passkeys 启动服务器

设置
步骤

按如下步骤设置使用条件 UI 的 Passkey 身份验证

  1. (如果尚不存在)注册一个新的必需操作以支持 WebAuthn 无密码。使用 启用 WebAuthn 身份验证器注册 中描述的步骤。注册 Webauthn Register Passwordless 操作。

  2. 配置 WebAuthn Passwordless Policy。在管理控制台的 Authentication 部分,在 PoliciesWebAuthn Passwordless Policy 选项卡中执行配置。当您为无密码登录场景配置策略时,将 User Verification Requirement 设置为 required,并将 Require discoverable credential 设置为 Yes。请注意,由于没有专门的无密码登录策略,因此无法混合使用用户验证=否/可发现凭据=否 的身份验证场景和无密码登录场景(用户验证=是/可发现凭据=是)。

    硬件 passkey 上的存储容量通常非常有限,这意味着您无法在您的 passkey 上存储许多可发现的凭据。但是,如果您使用由 Google 帐户支持的 Android 手机作为 passkey 设备或由 Bitwarden 支持的 iPhone,则此限制可能会得到缓解。
  3. 配置身份验证流。创建一个新的身份验证流,添加 Passkeys Conditional UI Authenticator 执行,并将执行的 Requirement 设置设置为 Required

    流的最终配置看起来类似于这样: 带有条件 UI 流的 Passkey 身份验证流

  4. 在 realm 中将上述流绑定为 browser 身份验证流,如上面的 WebAuthn 部分 中所述。

上面的身份验证流要求用户必须在其帐户上已拥有 passkey 凭据才能登录。此要求意味着 realm 中的所有用户都必须已设置 passkey。例如,可以通过启用用户注册来实现,如下所述。

设置用于 passkeys 条件 UI 的注册
  1. 为您的 realm 启用 注册

  2. 在 realm 的 身份验证流 中,选择流 registration 并将验证器 Password validation 切换为 Disabled。这意味着在此示例设置中,新注册的用户将不需要创建密码。用户必须始终使用 passkey 而不是密码。

  3. 返回 Authentication 选项卡的 Required actions 子选项卡,找到 Webauthn Register Passwordless 操作,并将其标记为 Set as default action。这意味着它将在用户注册后添加到所有新用户。

注册流设置的替代方法是将所需的 action WebAuthn Register Passwordless 添加到 Keycloak 已知的用户。配置了所需操作的用户将必须进行身份验证(例如,使用用户名/密码),然后将被提示注册一个 passkey,用于无密码登录身份验证。

我们计划改进可用性,并允许将条件 passkey 与现有的身份验证器和表单(例如默认的用户名/密码表单)集成。

Web Authn Level 3 开始,Resident KeyDiscoverable Credential 取代。

如果用户的浏览器支持 WebAuthn 条件 UI,则会显示以下屏幕。

带有条件 UI 的通行密钥身份验证

Passkey Authentication with Conditional UI

当用户单击 Select your passkey 文本框时,将显示用户在其上运行浏览器的设备上存储的 passkey 列表,如下所示。

带有条件 UI 自动填充的 Passkey 身份验证

Passkey Authentication with Conditional UI Autofill

如果用户的浏览器不支持 WebAuthn 条件 UI,则身份验证将回退到 LoginLess WebAuthn,如下所示。

带有条件 UI 的 Passkey 身份验证回退到 LoginLess WebAuthn

Passkey Authentication with Conditional UI falling back to LoginLess WebAuthn

恢复代码

恢复代码是由 Keycloak 自动生成的多个顺序一次性密码(目前为 12 个)。这些代码可以用作第二因素身份验证 (2FA),方法是将 Recovery Authentication Code Form 验证器添加到您的身份验证流程中。在流程中配置后,Keycloak 会要求用户输入顺序中的下一个生成的代码。当用户输入当前代码后,该代码将被删除,并且下次登录时将需要下一个代码。

由于其性质,恢复代码通常用作另一种 2FA 方法的备份。它们可以补充 OTP FormWebAuthn Authenticator,为登录 Keycloak 提供一种备用方法,例如,如果用于先前 2FA 方法的软件或硬件设备损坏或不可用。

RecoveryCodes 是 预览版,尚未完全支持。此功能默认情况下处于禁用状态。

要启用,请使用 --features=preview--features=recovery-codes 启动服务器

启用恢复代码所需操作

检查是否在 Keycloak 中启用了恢复代码操作

  1. 点击菜单中的 身份验证

  2. 点击 Required Actions(必需的操作) 选项卡。

  3. 确保 Recovery Authentication Codes 开关 Enabled 设置为 On

如果您希望所有新用户在首次登录时注册其恢复代码凭据,请将 Default Action 开关切换为 On

将恢复代码添加到浏览器流

以下过程将 Recovery Authentication Code Form 添加为默认 Browser 流中的另一种登录方式。

  1. 在 realm 菜单中单击 Authentication

  2. 单击浏览器流程。

  3. Action list 中选择 Duplicate 以创建内置 Browser 流的副本。

    例如,输入 Recovery Codes Browser 作为副本的名称。

  4. 单击复制

  5. 在流 Recovery Codes Browser Browser - Conditional OTP 中,单击 Add (+) 按钮,然后选择 Add Execution

  6. 筛选以查找 Recovery Authentication Code FormAdd 执行。

  7. 将新步骤的 requirement 设置为 Alternative

  8. 也将 OTP Form 的 requirement 设置为 Alternative

    恢复代码浏览器流

    Recovery Codes Browser flow

  9. 点击屏幕顶部的 操作 菜单。

  10. 从下拉列表中选择 Bind flow

  11. 从下拉列表中选择 Browser flow,以将此新流设置为 realm 的默认流。

  12. 点击 保存

通过此配置,两种 2FA 身份验证器(OTP FormRecovery Authentication Code Form)都是登录 Keycloak 的备用方式。如果用户配置了两种凭据类型,则默认情况下将显示 OTP Form,但另一个选项 Try Another Way 将可用,允许选择 Recovery Authentication Code 进行登录。

您可以在 2FA 条件工作流示例 中查看更多 2FA 配置示例。

创建恢复代码凭据

一旦启用恢复代码所需操作并且在流中管理了凭据类型,用户就可以请求创建自己的代码。该操作只是另一个 所需操作,可以在 Keycloak 中使用(直接由用户使用帐户控制台调用,或由管理员使用管理控制台分配)。

所需操作在执行时,会生成代码列表并将其呈现给用户。该操作提供打印、下载或复制代码列表的功能,以帮助用户将其存储在安全的地方。为了完成设置,应预先选中复选框 I have saved these codes somewhere safe

恢复身份验证代码设置页面

Recovery Authentication Codes setup page

可以随时重新创建恢复代码。

条件流中的条件

正如 执行要求 中提到的,Condition 执行只能包含在 Conditional 子流中。如果所有 Condition 执行都评估为 true,则 Conditional 子流充当 Required。您可以处理 Conditional 子流中的下一个执行。如果 Conditional 子流中包含的某些执行评估为 false,则整个子流将被视为 Disabled

可用条件

条件 - 用户角色

此执行能够确定用户是否具有由 User role 字段定义的角色。如果用户具有所需的角色,则该执行被视为 true,并评估其他执行。管理员必须定义以下字段

别名

描述执行的名称,该名称将显示在身份验证流中。

用户角色

用户应具有的角色才能执行此流程。要指定应用程序角色,语法为 appname.approle(例如 myapp.myrole)。

条件 - 用户已配置

这检查是否为用户配置了流中的其他执行。“执行要求”部分包含 OTP 表单的示例。

条件 - 用户属性

这检查用户是否设置了所需的属性:可选地,检查还可以评估组属性。可以否定输出,这意味着用户不应具有该属性。用户属性 部分显示了如何添加自定义属性。您可以提供以下字段

别名

描述执行的名称,该名称将显示在身份验证流中。

属性名称

要检查的属性的名称。

预期属性值

属性中的预期值。

包括组属性

如果为“开”,则条件检查任何加入的组是否具有一个属性与配置的名称和值匹配:此选项可能会影响性能

否定输出

您可以否定输出。换句话说,该属性不应存在。

条件 - 子流已执行

该条件检查先前的子流是否在身份验证过程中成功执行(或未执行)。因此,流可以根据先前子流的终止来触发其他步骤。存在以下配置字段

流名称

要检查是否已执行或未执行的子流名称。必需。

检查结果

条件何时评估为 true。如果 executed 在配置的子流以输出成功执行时返回 true,否则返回 false。如果 not-executed 在子流以输出成功执行时返回 false,否则返回 true(前一个选项的否定)。

条件 - 客户端范围

该条件评估配置的客户端范围是否作为请求身份验证的客户端的客户端范围存在。存在以下配置字段

客户端范围名称

客户端范围的名称,该名称应作为正在请求身份验证的客户端的客户端范围存在。如果请求的客户端范围是正在请求登录的客户端的默认客户端范围,则条件将评估为 true。如果请求的客户端范围是正在请求登录的客户端的可选客户端范围,则如果客户端在登录请求中发送了客户端范围(例如,在 OIDC/OAuth2 客户端登录的情况下通过 scope 参数),则条件将评估为 true。必需。

否定输出

对检查结果应用 NOT。当此项为 true 时,则仅当配置的客户端范围不存在时,条件才会评估为 true。

在条件流中显式拒绝/允许访问

您可以在条件流中允许或拒绝访问资源。两个身份验证器 Deny AccessAllow Access 通过条件控制对资源的访问。

允许访问

身份验证器将始终成功进行身份验证。此身份验证器不可配置。

拒绝访问

访问将始终被拒绝。您可以定义一条错误消息,该消息将显示给用户。您可以提供以下字段

别名

描述执行的名称,该名称将显示在身份验证流中。

错误消息

将向用户显示的错误消息。错误消息可以作为特定消息提供,也可以作为属性提供,以便将其用于本地化。(例如,“您没有 'admin' 角色。”,消息属性中的 my-property-deny)留空则使用定义为属性 access-denied 的默认消息。

这是一个示例,说明如何拒绝没有 role1 角色的所有用户的访问,并显示由属性 deny-role1 定义的错误消息。此示例包括 Condition - User RoleDeny Access 执行。

浏览器流程

Deny access flow

条件 - 用户角色配置

Deny access role settings

Deny Access 的配置非常简单。您可以像这样指定任意别名和所需的消息

Deny access execution settings

最后一件事情是在登录主题 messages_en.properties(对于英语)中定义带有错误消息的属性

deny-role1 = You do not have required role!

2FA 条件工作流示例

本节介绍了一些条件工作流的示例,这些示例以不同的方式集成了第二因素身份验证 (2FA)。这些示例复制了默认的 browser 流,并修改了 forms 子流中的配置。

条件 2FA 子流

默认的 browser 流使用 Conditional OTP 子流,该子流已经提供了带有 OTP 表单(一次性密码)的 2FA。遵循相同的思路,不同的 2FA 方法可以与 Condition - User Configured 集成。

2FA 所有备选项

2FA all alternative

forms 子流包含另一个带有 Condition - user configured2FA 条件子流。三个 2FA 步骤(OTP、Webauthn 和恢复代码)被允许作为备选项。如果为用户配置了这三个选项,用户将能够选择其中一个。由于子流是条件性的,因此如果未配置 2FA 凭据,则身份验证过程将成功完成。

条件 2FA 子流和拒绝访问

第二个示例延续了前一个示例。在 2FA 子流之后,另一个流 Deny access if no 2FA 用于检查之前的 2FA 是否未执行。在这种情况下(用户未配置 2FA 凭据),访问将被拒绝。

2FA 所有备选项和拒绝访问

2FA all alternative and deny access

Condition - sub-flow executed 配置用于检测 2FA 子流之前是否未执行。

子流执行的配置

Configuration for the sub-flow executed

步骤 Deny access 在未执行时拒绝身份验证。

带有 OTP 默认值的条件 2FA 子流

最后一个示例与前一个示例非常相似。步骤 OTP Form 配置为必需,而不是拒绝访问。

带有 OTP 默认值的 2FA 所有备选项

2FA all alternative with OTP default

通过此流程,如果用户没有配置任何 2FA 方法,则将强制执行 OTP 设置以继续登录。

身份验证会话

当在 Web 浏览器中首次打开登录页面时,Keycloak 会创建一个名为身份验证会话的对象,该对象存储有关请求的一些有用信息。每当在同一浏览器中的不同选项卡中打开新的登录页面时,Keycloak 都会创建一个名为身份验证子会话的新记录,该记录存储在身份验证会话中。身份验证请求可以来自任何类型的客户端,例如 Admin CLI。在这种情况下,也会创建一个新的身份验证会话,其中包含一个身份验证子会话。请注意,身份验证会话也可以通过浏览器流以外的其他方式创建。

身份验证会话通常在 30 分钟后过期(默认)。确切时间由管理控制台的 Sessions 选项卡中的 登录超时 开关指定,在配置 realm 时设置。

在更多浏览器选项卡中进行身份验证

如上一节所述,情况可能涉及尝试从单个浏览器的多个选项卡向 Keycloak 服务器进行身份验证的用户。但是,当该用户在一个浏览器选项卡中进行身份验证时,其他浏览器选项卡将自动重启身份验证。此身份验证的发生是由于 Keycloak 登录页面上提供的小型 javascript。重启通常会在其他浏览器选项卡中对用户进行身份验证,并重定向到客户端,因为现在存在 SSO 会话,这是因为用户刚刚在第一个浏览器选项卡中成功通过身份验证。当用户未在其他浏览器选项卡中自动进行身份验证时,存在一些罕见的例外情况,例如当使用 OIDC 参数 prompt=loginstep-up authentication 请求比当前已验证的因素更强的身份验证因素时。

在某些罕见情况下,可能会发生这种情况:在第一个浏览器选项卡中进行身份验证后,其他浏览器选项卡无法重启身份验证,因为身份验证会话已过期。在这种情况下,特定的浏览器选项卡将以协议特定的方式将有关身份验证会话过期的错误重定向回客户端。有关更多详细信息,请参阅 securing apps 部分中 OIDC 文档 的相应章节。当客户端应用程序收到此类错误时,它可以立即重新提交 OIDC/SAML 身份验证请求到 Keycloak,因为这通常应由于如前所述的现有 SSO 会话而自动对用户进行身份验证。因此,最终用户将在所有浏览器选项卡中自动进行身份验证。securing apps 部分中的 Keycloak JavaScript 适配器Keycloak 身份提供程序 支持自动处理此错误,并在这种情况下重试对 Keycloak 服务器的身份验证。

集成身份提供程序

身份代理是一个中介服务,用于连接服务提供商和身份提供商。身份代理与外部身份提供商建立关系,以使用提供商的身份来访问服务提供商公开的内部服务。

从用户的角度来看,身份代理提供了一种以用户为中心、集中化的方式来管理安全域和 realm 的身份。您可以将帐户与来自身份提供商的一个或多个身份链接起来,或者根据来自身份提供商的身份信息创建帐户。

身份提供商源自用于对用户进行身份验证并向用户发送身份验证和授权信息的特定协议。它可以是

  • 社交提供商,例如 Facebook、Google 或 Twitter。

  • 需要访问您服务的业务合作伙伴。

  • 您想要集成的基于云的身份服务。

通常,Keycloak 基于以下协议来构建身份提供商

  • SAML v2.0

  • OpenID Connect v1.0

  • OAuth v2.0

代理概述

当使用 Keycloak 作为身份代理时,Keycloak 不会强制用户提供凭据以在特定 realm 中进行身份验证。Keycloak 显示身份提供商列表,用户可以从中进行身份验证。

如果您配置了默认身份提供商,Keycloak 会将用户重定向到默认提供商。

不同的协议可能需要不同的身份验证流程。Keycloak 支持的所有身份提供商都使用以下流程。

身份代理流程

Identity broker flow

  1. 未经身份验证的用户在客户端应用程序中请求受保护的资源。

  2. 客户端应用程序将用户重定向到 Keycloak 进行身份验证。

  3. Keycloak 显示登录页面,其中包含在 realm 中配置的身份提供商列表。

  4. 用户通过单击其按钮或链接来选择其中一个身份提供商。

  5. Keycloak 向目标身份提供商发出身份验证请求,请求身份验证,并将用户重定向到身份提供商的登录页面。管理员已为管理控制台的身份提供商设置了连接属性和其他配置选项。

  6. 用户提供凭据或同意通过身份提供商进行身份验证。

  7. 在身份提供商成功进行身份验证后,用户会重定向回 Keycloak 并收到身份验证响应。通常,响应包含一个安全令牌,Keycloak 使用该令牌来信任身份提供商的身份验证并检索用户信息。

  8. Keycloak 检查来自身份提供商的响应是否有效。如果有效,Keycloak 会导入并创建一个用户(如果该用户尚不存在)。如果令牌不包含该信息,Keycloak 可能会向身份提供商请求更多用户信息。此行为称为身份联合。如果用户已存在,Keycloak 可能会要求用户将从身份提供商返回的身份与现有帐户链接起来。此行为称为帐户链接。使用 Keycloak,您可以配置帐户链接,并在首次登录流程中指定它。在此步骤中,Keycloak 对用户进行身份验证,并颁发其令牌以访问服务提供商中请求的资源。

  9. 当用户通过身份验证后,Keycloak 会通过发送先前在本地身份验证期间颁发的令牌,将用户重定向到服务提供商。

  10. 服务提供商从 Keycloak 接收令牌,并允许访问受保护的资源。

此流程可能存在变体。例如,客户端应用程序可以请求特定的身份提供商,而不是显示身份提供商列表,或者您可以将 Keycloak 设置为强制用户在联合其身份之前提供其他信息。

在身份验证过程结束时,Keycloak 会向客户端应用程序颁发其令牌。客户端应用程序与外部身份提供商是分离的,因此它们看不到客户端应用程序的协议或它们如何验证用户的身份。提供商只需要了解 Keycloak。

默认身份提供商

Keycloak 可以重定向到身份提供商,而不是显示登录表单。要启用此重定向

步骤
  1. 点击菜单中的 身份验证

  2. 单击浏览器流程。

  3. 单击 身份提供商重定向器 行上的齿轮图标 ⚙️

  4. 默认身份提供商 设置为您要将用户重定向到的身份提供商。

如果 Keycloak 找不到配置的默认身份提供商,则会显示登录表单。

此身份验证器负责处理 kc_idp_hint 查询参数。有关更多信息,请参阅 客户端建议的身份提供商 部分。

身份验证器将重定向到身份提供商,并且身份验证将委派给身份提供商。在与身份提供商的登录成功完成后,browser 身份验证流程将不会继续。如果您想在身份提供商登录后执行其他步骤(例如,双因素身份验证),则可能需要配置 登录后流程

常规配置

身份代理配置的基础是身份提供商 (IDP)。Keycloak 为每个 realm 创建身份提供商,并默认对每个应用程序启用它们。来自 realm 的用户在登录应用程序时可以使用任何已注册的身份提供商。

步骤
  1. 单击菜单中的 身份提供商

    身份提供商

    Identity Providers

  2. 选择一个身份提供商。Keycloak 显示您选择的身份提供商的配置页面。

    添加 Facebook 身份提供商

    Add Facebook Identity Provider

    当您配置身份提供商时,身份提供商会作为选项显示在 Keycloak 登录页面上。您可以为每个身份提供商在登录屏幕上放置自定义图标。有关更多信息,请参阅 自定义图标

    IDP 登录页面

    identity provider login page

    社交

    社交提供商在您的 realm 中启用社交身份验证。借助 Keycloak,用户可以使用社交网络帐户登录您的应用程序。支持的提供商包括 Twitter、Facebook、Google、LinkedIn、Instagram、Microsoft、PayPal、Openshift v4、GitHub、GitLab、Bitbucket 和 Stack Overflow。

    基于协议

    基于协议的提供商依赖于特定协议来对用户进行身份验证和授权。使用这些提供商,您可以连接到任何符合特定协议的身份提供商。Keycloak 提供对 SAML v2.0 和 OpenID Connect v1.0 协议的支持。您可以配置和代理基于这些开放标准的任何身份提供商。

尽管每种身份提供商都有其配置选项,但所有身份提供商都共享一个通用配置。以下是可用的配置选项

表 1. 通用配置
配置 描述

别名

别名是身份提供商的唯一标识符,并引用内部身份提供商。Keycloak 使用别名来构建 OpenID Connect 协议的重定向 URI,这些协议需要重定向 URI 或回调 URL 才能与身份提供商通信。所有身份提供商都必须具有别名。别名示例包括 facebookgoogleidp.acme.com

已启用

切换提供商的开启或关闭状态。

在登录页面隐藏

开启时,Keycloak 不会在登录页面上将此提供商显示为登录选项。客户端可以使用 URL 中的“kc_idp_hint”参数请求此提供商以进行登录。

仅账户链接

开启时,Keycloak 会将现有账户与此提供商链接。此提供商无法让用户登录,并且 Keycloak 不会在登录页面上将此提供商显示为选项。

存储令牌

开启时,Keycloak 会存储来自身份提供商的令牌。

已存储令牌可读

开启时,用户可以检索已存储的身份提供商令牌。此操作也适用于代理客户端级别的角色读取令牌

信任电子邮件

开启时,Keycloak 信任来自身份提供商的电子邮件地址。如果 realm 需要电子邮件验证,则从此身份提供商登录的用户无需执行电子邮件验证过程。

GUI 顺序

登录页面上可用身份提供商的排序顺序。

验证必要声明

开启时,身份提供商颁发的 ID 令牌必须具有特定的声明,否则用户无法通过此代理进行身份验证

必要声明

验证必要声明开启时,要过滤的 JWT 令牌声明的名称(匹配区分大小写)

必要声明值

验证必要声明开启时,要匹配的 JWT 令牌声明的值(支持正则表达式格式)

首次登录流程

当用户首次使用此身份提供商登录 Keycloak 时,Keycloak 触发的身份验证流程。

登录后流程

当用户完成使用外部身份提供商登录后,Keycloak 触发的身份验证流程。

同步模式

通过映射器更新来自身份提供商的用户信息的策略。当选择 legacy 时,Keycloak 使用当前行为。Import 不更新用户数据,而 force 在可能的情况下更新用户数据。有关更多信息,请参阅 身份提供商映射器

用户名区分大小写

如果启用,则在联合用户时,来自身份提供商的原始用户名将保持原样。否则,来自身份提供商的用户名将转换为小写,如果区分大小写,则可能与原始值不匹配。此设置仅影响与联合身份关联的用户名,因为服务器中的用户名始终为小写。

社交身份提供商

社交身份提供商可以将身份验证委托给受信任、受尊重的社交媒体帐户。Keycloak 包括对社交网络的支持,例如 Google、Facebook、Twitter、GitHub、LinkedIn、Microsoft 和 Stack Overflow。

Bitbucket

要使用 Bitbucket 登录,请执行以下步骤。

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 Bitbucket

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,执行 Bitbucket Cloud 上的 OAuth 流程。当您单击添加 Consumer

    1. 重定向 URI 的值粘贴到 回调 URL 字段中。

    2. 确保您在 账户 部分中选择 EmailRead,以允许您的应用程序读取电子邮件。

  5. 记下 Bitbucket 在您创建 consumer 时显示的 KeySecret 值。

  6. 在 Keycloak 中,将 Key 的值粘贴到 客户端 ID 字段中。

  7. 在 Keycloak 中,将 Secret 的值粘贴到 客户端密钥 字段中。

  8. 点击 添加

Facebook

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 Facebook

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,打开 Meta for Developers

    1. 单击我的应用

    2. 选择创建应用

      添加用例

      Add a use case

    3. 选择其他

      选择应用类型

      Select an app type

    4. 选择 Consumer

      创建应用

      Create an app

    5. 填写所有必填字段。

    6. 单击创建应用。Meta 然后会将您带到仪表板。

      添加产品

      Add Product

    7. Facebook 登录框中单击 设置

    8. 选择 Web

    9. 重定向 URI 的值输入到 网站 URL 字段中,然后单击 保存

    10. 在导航面板中,选择 应用设置 - 基本

    11. 应用密钥 字段中单击 显示

    12. 记下 应用 ID应用密钥

  5. App IDApp Secret 值从您的 Facebook 应用输入到 Keycloak 中的 客户端 ID客户端密钥 字段中。

  6. 单击添加

  7. 默认 Scope 字段中输入所需的 scope。默认情况下,Keycloak 使用 email scope。有关 Facebook scope 的更多信息,请参阅 Graph API

默认情况下,Keycloak 将配置文件请求发送到 graph.facebook.com/me?fields=id,name,email,first_name,last_name。响应仅包含 id、name、email、first_name 和 last_name 字段。要从 Facebook 配置文件中获取其他字段,请添加相应的 scope 并在 其他用户配置文件字段 配置选项字段中添加字段名称。

GitHub

要使用 GitHub 登录,请执行以下步骤。

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 Github

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,创建一个 OAUTH 应用

    1. 在创建应用时,将 重定向 URI 的值输入到 授权回调 URL 字段中。

    2. 记下您的 OAUTH 应用管理页面上的 Client IDClient secret

  5. 在 Keycloak 中,将 Client ID 的值粘贴到 客户端 ID 字段中。

  6. 在 Keycloak 中,将 Client secret 的值粘贴到 客户端密钥 字段中。

  7. 点击 添加

GitLab

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 GitLab

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,添加一个新的 GitLab 应用程序

    1. 使用剪贴板中的 重定向 URI 作为 重定向 URI

    2. 保存应用程序时,记下 应用程序 ID密钥

  5. 在 Keycloak 中,将 Application ID 的值粘贴到 客户端 ID 字段中。

  6. 在 Keycloak 中,将 Secret 的值粘贴到 客户端密钥 字段中。

  7. 点击 添加

Google

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 Google

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,打开 Google Cloud Platform 控制台

  5. 在您的 Google 应用的 Google 仪表板中,在左侧的导航菜单中,将鼠标悬停在 API 和服务 上,然后单击 OAuth 同意屏幕 选项。创建一个同意屏幕,确保同意屏幕的用户类型为 外部

  6. 在 Google 仪表板中

    1. 单击 凭据 菜单。

    2. 单击 创建凭据 - OAuth 客户端 ID

    3. 应用程序类型 列表中,选择 Web 应用程序

    4. 使用剪贴板中的 重定向 URI 作为 已授权的重定向 URI

    5. 单击“创建”。

    6. 记下 您的客户端 ID您的客户端密钥

  7. 在 Keycloak 中,将 Your Client ID 的值粘贴到 客户端 ID 字段中。

  8. 在 Keycloak 中,将 Your Client secret 的值粘贴到 客户端密钥 字段中。

  9. 单击添加

  10. 默认 Scope 字段中输入所需的 scope。默认情况下,Keycloak 使用以下 scope:openid profile email。有关 Google scope 的列表,请参阅 OAuth Playground

  11. 要仅限制对您的 GSuite 组织成员的访问,请在 托管域 字段中输入 G Suite 域名。

  12. 点击 保存

Instagram

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商列表中,选择 Instagram

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器选项卡中,打开 Meta for Developers

    1. 单击我的应用

    2. 选择创建应用

      添加用例

      Add a use case

    3. 选择其他

      选择应用类型

      Select an app type

    4. 选择 Consumer

      创建应用

      Create an app

    5. 填写所有必填字段。

    6. 单击创建应用。Meta 然后会将您带到仪表板。

    7. 在导航面板中,选择 应用设置 - 基本

    8. 在页面底部选择 + 添加平台

    9. 单击 [网站]

    10. 输入您网站的 URL。

      添加产品

      Add Product

    11. 从菜单中选择 仪表板

    12. Instagram Basic Display 框中单击 设置

    13. 单击 创建新应用

      创建一个新的 Instagram 应用 ID

      Create a New Instagram App ID

    14. 显示名称 字段中输入一个值。

      设置应用

      Setup the App

    15. 将来自 Keycloak 的 重定向 URL 粘贴到 有效的 OAuth 重定向 URI 字段中。

    16. 将来自 Keycloak 的 重定向 URL 粘贴到 取消授权回调 URL 字段中。

    17. 将来自 Keycloak 的 重定向 URL 粘贴到 数据删除请求 URL 字段中。

    18. Instagram 应用密钥 字段中单击 显示

    19. 记下 Instagram 应用 IDInstagram 应用密钥

    20. 单击 应用审核 - 请求

    21. 按照屏幕上的说明进行操作。

  5. 在 Keycloak 中,将 Instagram App ID 的值粘贴到 客户端 ID 字段中。

  6. 在 Keycloak 中,将 Instagram App Secret 的值粘贴到 客户端密钥 字段中。

  7. 点击 添加

LinkedIn

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 LinkedIn

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器标签页中,在 LinkedIn 开发者门户中创建应用

    1. 创建应用后,点击 Auth 标签页。

    2. Redirect URI 的值输入到 Authorized redirect URLs for your app 字段中。

    3. 记下 Your Client IDYour Client Secret

    4. 点击 Products 标签页,并为 Sign In with LinkedIn using OpenID Connect 产品请求访问权限

  5. 在 Keycloak 中,将 Client ID 的值粘贴到 客户端 ID 字段中。

  6. 在 Keycloak 中,将 Client Secret 的值粘贴到 Client Secret 字段中。

  7. 点击 添加

Microsoft

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 Microsoft

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器标签页中,在 Microsoft AzureApp registrations 下注册一个应用。

    1. 在 Redirect URI 部分,选择 Web 作为平台,并将 Redirect URI 的值粘贴到该字段中。

    2. App registrations 下找到您的应用,并在 Certificates & secrets 部分添加一个新的客户端密钥。

    3. 记下已创建密钥的 Value

    4. Overview 部分记下 Application (client) ID

  5. 在 Keycloak 中,将 Application (client) ID 的值粘贴到 Client ID 字段中。

  6. 在 Keycloak 中,将密钥的 Value 粘贴到 Client Secret 字段中。

  7. 点击 添加

OpenShift 4

先决条件
  1. OpenShift 4 实例的证书存储在 Keycloak Truststore 中。

  2. 配置为使用 truststore 的 Keycloak 服务器。有关更多信息,请参阅配置 Truststore 指南。

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 Openshift v4

  3. 输入 Client IDClient Secret,并在 Base URL 字段中,输入您的 OpenShift 4 实例的 API URL。此外,您可以将 Redirect URI 复制到剪贴板。

    添加身份提供商

    Add Identity Provider

  4. 通过 OpenShift 4 控制台(Home → API Explorer → OAuth Client → Instances)或使用 oc 命令行工具注册您的客户端。

    $ oc create -f <(echo '
    kind: OAuthClient
    apiVersion: oauth.openshift.io/v1
    metadata:
     name: kc-client (1)
    secret: "..." (2)
    redirectURIs:
     - "<here you can paste the Redirect URI that you copied in the previous step>" (3)
    grantMethod: prompt (4)
    ')
1 您的 OAuth 客户端的 name。在向 <openshift_master>/oauth/authorize<openshift_master>/oauth/token 发出请求时,作为 client_id 请求参数传递。name 参数在 OAuthClient 对象和 Keycloak 配置中必须相同。
2 Keycloak 用作 client_secret 请求参数的 secret
3 在向 <openshift_master>/oauth/authorize<openshift_master>/oauth/token 发出的请求中指定的 redirect_uri 参数必须等于(或以...为前缀)redirectURIs 中的 URI 之一。正确配置它的最简单方法是从 Keycloak OpenShift 4 身份提供程序配置页面(Redirect URI 字段)复制粘贴它。
4 grantMethod Keycloak 用于确定当此客户端请求令牌但尚未获得用户授权时要执行的操作。

最后,您应该在 Keycloak 实例的登录页面上看到 OpenShift 4 身份提供程序。点击它后,您应该被重定向到 OpenShift 4 登录页面。

结果

Result

有关更多信息,请参阅官方 OpenShift 文档

PayPal

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 PayPal

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器标签页中,打开 PayPal 开发者应用程序区域

    1. 点击 Create App 以创建一个 PayPal 应用。

    2. 记下 Client IDClient Secret。点击 Show 链接以查看密钥。

    3. 确保选中 Log in with PayPal

    4. 在 Log in with PayPal 下,点击 Advanced Settings

    5. Return URL 字段的值设置为 Keycloak 中的 Redirect URI 值。请注意,URL 不能包含 localhost。如果您想在本地使用 Keycloak,请将 Return URL 中的 localhost 替换为 127.0.0.1,然后使用浏览器中的 127.0.0.1 而不是 localhost 访问 Keycloak。

    6. 确保选中 Full NameEmail 字段。

    7. 点击 Save,然后点击 Save Changes

  5. 在 Keycloak 中,将 Client ID 的值粘贴到 客户端 ID 字段中。

  6. 在 Keycloak 中,将 Secret key 1 的值粘贴到 Client Secret 字段中。

  7. 点击 添加

Stack Overflow

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 Stack Overflow

    添加身份提供商

    Add Identity Provider

  3. 在单独的浏览器标签页中,登录 Stack Apps 上注册您的应用程序

    注册应用程序

    Register Application

    1. Application Name 字段中输入您的应用程序名称。

    2. OAuth Domain 字段中输入 OAuth 域。

    3. 点击 Register Your Application

      设置

      Settings

  4. 记下 Client IdClient SecretKey

  5. 在 Keycloak 中,将 Client Id 的值粘贴到 Client ID 字段中。

  6. 在 Keycloak 中,将 Client Secret 的值粘贴到 Client Secret 字段中。

  7. 在 Keycloak 中,将 Key 的值粘贴到 Key 字段中。

  8. 点击 添加

Twitter

先决条件
  1. 一个 Twitter 开发者帐户。

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供程序列表中,选择 Twitter

    添加身份提供商

    Add Identity Provider

  3. 重定向 URI 的值复制到剪贴板。

  4. 在单独的浏览器标签页中,在 Twitter 应用程序管理中创建一个应用。

    1. 输入应用名称,然后点击 Next

    2. 记下 API KeyAPI Key Secret 的值,然后点击 App settings

    3. User authentication settings 部分,点击 Set up 按钮。

    4. 选择 Web App 作为 Type of App

    5. Redirect URL 的值粘贴到 Callback URI / Redirect URL 字段中。

    6. Website URL 的值可以是除 localhost 之外的任何有效 URL。

    7. 点击 Save,然后点击 Done

  5. 在 Keycloak 中,将 API Key 的值粘贴到 Client ID 字段中。

  6. 在 Keycloak 中,将 API Key Secret 的值粘贴到 Client Secret 字段中。

  7. 点击 添加

OpenID Connect v1.0 身份提供程序

Keycloak 基于 OpenID Connect 协议代理身份提供程序。这些身份提供程序 (IDP) 必须支持规范中定义的授权码流程,以验证用户身份并授权访问。

步骤
  1. 单击菜单中的 身份提供商

  2. Add provider 列表中,选择 OpenID Connect v1.0

    添加身份提供商

    Add Identity Provider

  3. 输入您的初始配置选项。有关配置选项的更多信息,请参阅通用 IDP 配置

    表 2. OpenID Connect 配置
    配置 描述

    授权 URL

    OIDC 协议要求的授权 URL 端点。

    令牌 URL

    OIDC 协议要求的令牌 URL 端点。

    注销 URL

    OIDC 协议中的注销 URL 端点。此值为可选。

    后端注销

    发送到 IDP 的后台、带外 REST 请求,用于注销用户。某些 IDP 仅通过浏览器重定向执行注销,因为它们可能使用浏览器 Cookie 识别会话。

    用户信息 URL

    OIDC 协议定义的端点。此端点指向用户个人资料信息。

    客户端身份验证

    定义 Keycloak 与授权码流程一起使用的客户端身份验证方法。对于使用私钥签名的 JWT,Keycloak 使用 realm 私钥。在其他情况下,定义客户端密钥。有关更多信息,请参阅客户端身份验证规范

    客户端 ID

    充当外部 IDP 的 OIDC 客户端的 realm。如果您使用授权码流程与外部 IDP 交互,则 realm 必须具有 OIDC 客户端 ID。

    客户端密钥

    来自外部vault的客户端密钥。如果您使用授权码流程,则此密钥是必需的。

    客户端断言签名算法

    用于创建 JWT 断言作为客户端身份验证的签名算法。对于使用私钥签名的 JWT 或作为 jwt 的客户端密钥,这是必需的。如果未指定算法,则会采用以下算法。在使用私钥签名的 JWT 的情况下,采用 RS256。在作为 jwt 的客户端密钥的情况下,采用 HS256

    客户端断言受众

    用于客户端断言的受众。默认值为 IDP 的令牌端点 URL。

    颁发者

    Keycloak 针对此值验证来自 IDP 的响应中的颁发者声明。

    默认范围

    Keycloak 随身份验证请求发送的 OIDC 范围列表。默认值为 openid。每个范围用空格分隔。

    提示

    OIDC 规范中的提示参数。通过此参数,您可以强制重新身份验证和其他选项。有关更多详细信息,请参阅规范。

    接受来自客户端的 prompt=none 转发

    指定 IDP 是否接受包含 prompt=none 查询参数的转发身份验证请求。如果 realm 收到带有 prompt=none 的身份验证请求,则 realm 会检查用户当前是否已通过身份验证,如果用户尚未登录,则返回 login_required 错误。当 Keycloak 确定身份验证请求的默认 IDP 时(使用 kc_idp_hint 查询参数或 realm 具有默认 IDP),您可以将带有 prompt=none 的身份验证请求转发到默认 IDP。默认 IDP 在此处检查用户的身份验证。由于并非所有 IDP 都支持带有 prompt=none 的请求,因此 Keycloak 使用此开关来指示默认 IDP 在重定向身份验证请求之前支持该参数。

    如果用户在 IDP 中未通过身份验证,则客户端仍然会收到 login_required 错误。如果用户在 IDP 中已通过身份验证,则如果 Keycloak 必须显示需要用户交互的身份验证页面,则客户端仍然可能收到 interaction_required 错误。此身份验证包括必需的操作(例如,密码更改)、同意屏幕以及设置为通过 first broker login 流程或 post broker login 流程显示的屏幕。

    验证签名

    指定 Keycloak 是否验证此 IDP 签名的外部 ID 令牌上的签名。如果为开启,则 Keycloak 必须知道外部 OIDC IDP 的公钥。出于性能目的,Keycloak 缓存外部 OIDC 身份提供程序的公钥。

    使用 JWKS URL

    如果 Validate Signatures开启,则此开关适用。如果 Use JWKS URL开启,则 Keycloak 从 JWKS URL 下载 IDP 的公钥。当身份提供程序生成新的密钥对时,会下载新密钥。如果为关闭,则 Keycloak 使用其数据库中的公钥(或证书),因此当 IDP 密钥对更改时,也将新密钥导入到 Keycloak 数据库。

    JWKS URL

    指向 IDP JWK 密钥位置的 URL。有关更多信息,请参阅 JWK 规范。如果您使用外部 Keycloak 作为 IDP,则可以使用类似 http://broker-keycloak:8180/realms/test/protocol/openid-connect/certs 的 URL,如果您的代理 Keycloak 运行在 http://broker-keycloak:8180 上,并且其 realm 为 test

    验证公钥

    PEM 格式的公钥,Keycloak 使用此公钥来验证外部 IDP 签名。如果 使用 JWKS URL关闭,则应用此密钥。

    验证公钥 ID

    如果使用 JWKS URL关闭,则应用此设置。此设置指定 PEM 格式公钥的 ID。由于没有从密钥计算密钥 ID 的标准方法,因此外部身份提供商可以使用与 Keycloak 不同的算法。如果未指定此字段的值,则 Keycloak 将对所有请求使用验证公钥,而不管外部 IDP 发送的密钥 ID 如何。当开启时,此字段的值是 Keycloak 用于验证来自提供商的签名的密钥 ID,并且必须与 IDP 指定的密钥 ID 匹配。

您可以通过提供指向 OpenID 提供商元数据的 URL 或文件来导入所有此配置数据。如果您连接到 Keycloak 外部 IDP,则可以从 <root>/realms/{realm-name}/.well-known/openid-configuration 导入 IDP 设置。此链接是一个 JSON 文档,描述了有关 IDP 的元数据。

如果您想在提供商中使用 Json Web Encryption (JWE) ID 令牌或 UserInfo 响应,则 IDP 需要知道与 Keycloak 一起使用的公钥。提供商使用为不同加密算法定义的 realm 密钥 来解密令牌。Keycloak 提供了一个标准的 JWKS 端点,IDP 可以使用该端点自动下载密钥。

SAML v2.0 身份提供商

Keycloak 可以代理基于 SAML v2.0 协议的身份提供商。

步骤
  1. 单击菜单中的 身份提供商

  2. 添加提供商 列表中,选择 SAML v2.0

    添加身份提供商

    Add Identity Provider

  3. 输入您的初始配置选项。有关配置选项的更多信息,请参阅通用 IDP 配置

表 3. SAML 配置
配置 描述

服务提供商实体 ID

远程身份提供商用于标识来自此服务提供商的请求的 SAML 实体 ID。默认情况下,此设置设置为 realm 的基本 URL <root>/realms/{realm-name}

身份提供商实体 ID

用于验证接收到的 SAML 断言的颁发者的实体 ID。如果为空,则不执行颁发者验证。

单点登录服务 URL

启动身份验证过程的 SAML 端点。如果您的 SAML IDP 发布了 IDP 实体描述符,则此字段的值将在其中指定。

Artifact 服务 URL

SAML Artifact 解析端点。如果您的 SAML IDP 发布了 IDP 实体描述符,则此字段的值将在其中指定。

单点注销服务 URL

SAML 注销端点。如果您的 SAML IDP 发布了 IDP 实体描述符,则此字段的值将在其中指定。

后端注销

如果您的 SAML IDP 支持后通道注销,请将此开关切换为开启

NameID 策略格式

与名称标识符格式对应的 URI 引用。默认情况下,Keycloak 将其设置为 urn:oasis:names:tc:SAML:2.0:nameid-format:persistent

主体类型

指定 SAML 断言的哪个部分将用于识别和跟踪外部用户身份。可以是主体 NameID 或 SAML 属性(按名称或友好名称)。主体 NameID 值不能与 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' NameID 策略格式值一起设置。

主体属性

如果主体类型为非空,则此字段指定标识属性的名称(“属性 [名称]”)或友好名称(“属性 [友好名称]”)。

允许创建

允许外部身份提供商创建新的标识符来表示主体。

HTTP-POST 绑定响应

控制响应外部 IDP 发送的任何 SAML 请求的 SAML 绑定。当关闭时,Keycloak 使用重定向绑定。

ARTIFACT 绑定响应

控制响应外部 IDP 发送的任何 SAML 请求的 SAML 绑定。当关闭时,Keycloak 评估 HTTP-POST 绑定响应配置。

HTTP-POST 绑定用于 AuthnRequest

控制从外部 IDP 请求身份验证时的 SAML 绑定。当关闭时,Keycloak 使用重定向绑定。

需要签名 AuthnRequest

开启时,Keycloak 使用 realm 的密钥对对发送到外部 SAML IDP 的请求进行签名。

需要签名断言

指示此服务提供商是否期望签名的断言。

需要加密断言

指示此服务提供商是否期望加密的断言。

签名算法

如果需要签名 AuthnRequest开启,则要使用的签名算法。请注意,基于 SHA1 的算法已被弃用,并可能在未来的版本中删除。我们建议使用比 *_SHA1 更安全的算法。此外,对于 *_SHA1 算法,如果 SAML 身份提供商(例如 Keycloak 的另一个实例)在 Java 17 或更高版本上运行,则验证签名将不起作用。

加密算法

SAML IDP 用于加密 SAML 文档、断言或 ID 的加密算法。用于解密 SAML 文档部分的相应解密密钥将根据此配置的算法选择,并且应在 realm 密钥中可用,以用于加密 (ENC)。如果未配置算法,则允许任何支持的算法,并且将根据 SAML 文档本身中指定的算法选择解密密钥。

SAML 签名密钥名称

使用 POST 绑定发送的已签名 SAML 文档在 KeyName 元素中包含签名密钥的标识,默认情况下,该元素包含 Keycloak 密钥 ID。外部 SAML IDP 可能期望不同的密钥名称。此开关控制 KeyName 是否包含:* KEY_ID - 密钥 ID。* CERT_SUBJECT - 来自证书的主题,该证书与 realm 密钥相对应。Microsoft Active Directory Federation Services 期望 CERT_SUBJECT。* NONE - Keycloak 从 SAML 消息中省略密钥名称提示。

强制身份验证

即使在用户已经登录的情况下,用户也必须在外部 IDP 输入其凭据。

验证签名

开启时,realm 期望来自外部 IDP 的 SAML 请求和响应是数字签名的。

元数据描述符 URL

身份提供商发布 IDPSSODescriptor 元数据的外部 URL。当单击 重新加载密钥导入密钥 操作时,此 URL 用于下载身份提供商证书。

使用元数据描述符 URL

开启时,用于验证签名的证书会自动从 元数据描述符 URL 下载并缓存在 Keycloak 中。SAML 提供商可以通过两种不同的方式验证签名。如果请求特定的证书(通常在 POST 绑定中),并且该证书不在缓存中,则会自动从 URL 刷新证书。如果请求所有证书以验证签名(REDIRECT 绑定),则仅在最大缓存时间后才完成刷新(有关缓存如何工作的更多信息,请参阅所有提供商配置指南中的 public-key-storage spi)。也可以使用身份提供商页面中的 重新加载密钥 操作手动更新缓存。

当选项为关闭时,验证 X509 证书 中的证书用于验证签名。

验证 X509 证书

使用元数据描述符 URL关闭时,Keycloak 用于验证来自外部 IDP 的 SAML 请求和响应的签名的公钥证书。可以输入多个证书,并用逗号 (,) 分隔。可以通过单击身份提供商页面中的 导入密钥 操作从 元数据描述符 URL 重新导入证书。该操作下载元数据端点中的当前证书,并将它们分配给同一选项中的配置。您需要单击 保存 以最终存储重新导入的证书。

签署服务提供商元数据

开启时,Keycloak 使用 realm 的密钥对对 SAML 服务提供商元数据描述符 进行签名。

传递主题

控制 Keycloak 是否将 login_hint 查询参数转发到 IDP。Keycloak 将此字段的值添加到 AuthnRequest 的 Subject 中的 login_hint 参数,以便目标提供商可以预填充其登录表单。

属性消费服务索引

标识要向远程 IDP 请求的属性集。Keycloak 自动将身份提供商配置中映射的属性添加到自动生成的 SP 元数据文档。

属性消费服务名称

在自动生成的 SP 元数据文档中声明的属性集的描述性名称。

您可以通过提供指向外部 IDP 的 SAML IDP 实体描述符的 URL 或文件来导入所有配置数据。如果您连接到 Keycloak 外部 IDP,则可以从 URL <root>/realms/{realm-name}/protocol/saml/descriptor 导入 IDP 设置。此链接是一个 XML 文档,描述了有关 IDP 的元数据。您还可以通过提供指向外部 SAML IDP 的实体描述符的 URL 或 XML 文件来导入所有此配置数据以进行连接。

请求特定的 AuthnContext

身份提供商方便客户端指定验证用户身份的身份验证方法的约束。例如,请求 MFA、Kerberos 身份验证或安全要求。这些约束使用特定的 AuthnContext 标准。客户端可以请求一个或多个标准,并指定身份提供商必须如何匹配请求的 AuthnContext,完全匹配,或通过满足其他等效项来匹配。

您可以通过在“请求的 AuthnContext 约束”部分中添加 ClassRefs 或 DeclRefs 来列出您的服务提供商需要的标准。通常,您需要提供 ClassRefs 或 DeclRefs 中的一个,因此请查看您的身份提供商文档,了解支持哪些值。如果不存在 ClassRefs 或 DeclRefs,则身份提供商不会强制执行其他约束。

表 4. 请求的 AuthnContext 约束
配置 描述

比较

身份提供商用于评估上下文要求的方法。可用值为 ExactMinimumMaximumBetter。默认值为 Exact

AuthnContext ClassRefs

描述所需标准的 AuthnContext ClassRefs。

AuthnContext DeclRefs

描述所需标准的 AuthnContext DeclRefs。

SP 描述符

当您访问提供商的 SAML SP 元数据时,请在身份提供商配置设置中查找 端点 项。它包含一个 SAML 2.0 服务提供商元数据 链接,该链接为服务提供商生成 SAML 实体描述符。您可以下载描述符或复制其 URL,然后将其导入到远程身份提供商中。

此元数据也可以通过访问以下 URL 公开获得

http[s]://{host:port}/realms/{realm-name}/broker/{broker-alias}/endpoint/descriptor

在访问描述符之前,请确保保存任何配置更改。

在 SAML 请求中发送主题

默认情况下,指向 SAML 身份提供商的社交按钮会将用户重定向到以下登录 URL

http[s]://{host:port}/realms/${realm-name}/broker/{broker-alias}/login

将名为 login_hint 的查询参数添加到此 URL 会将参数的值作为 Subject 属性添加到 SAML 请求中。如果此查询参数为空,则 Keycloak 不会向请求添加主题。

启用“传递主题”选项以在 SAML 请求中发送主题。

客户端建议的身份提供商

OIDC 应用程序可以通过提示他们想要使用的身份提供商来绕过 Keycloak 登录页面。您可以通过在授权码流程授权端点中设置 kc_idp_hint 查询参数来启用此功能。

使用 Keycloak OIDC 客户端适配器,您可以在访问应用程序中的受保护资源时指定此查询参数。

例如

GET /myapplication.com?kc_idp_hint=facebook HTTP/1.1
Host: localhost:8080

在这种情况下,您的 realm 必须具有别名为 facebook 的身份提供商。如果此提供商不存在,则会显示登录表单。

如果您使用的是 JavaScript 适配器,您也可以通过以下方式实现相同的行为

const keycloak = new Keycloak({
        url: "http://keycloak-server",
        realm: "my-realm",
        clientId: "my-app"
);

await keycloak.createLoginUrl({
        idpHint: 'facebook'
});

使用 kc_idp_hint 查询参数,如果您为 身份提供商重定向器 身份验证器配置了一个默认身份提供商,则客户端可以覆盖该默认身份提供商。客户端可以通过将 kc_idp_hint 查询参数设置为空值来禁用自动重定向。

映射声明和断言

您可以将外部 IDP(您正在使用其进行身份验证)提供的 SAML 和 OpenID Connect 元数据导入到 realm 中。导入后,您可以提取用户配置文件元数据和其他信息,以便您可以将其提供给您的应用程序。

每个使用外部身份提供商登录到您的 realm 的用户在本地 Keycloak 数据库中都有一个条目,该条目基于来自 SAML 或 OIDC 断言和声明的元数据。

步骤
  1. 单击菜单中的 身份提供商

  2. 在列表中选择一个身份提供商。

  3. 单击 映射器 选项卡。

    身份提供商映射器

    identity provider mappers

  4. 单击 添加映射器

    身份提供商映射器

    identity provider mapper

  5. 同步模式覆盖 选择一个值。当用户根据此设置重复登录时,映射器会更新用户信息。

    1. 选择 legacy 以使用以前 Keycloak 版本的行为。

    2. 选择 import 以从用户首次通过特定身份提供商首次登录 Keycloak 期间在 Keycloak 中创建用户时导入数据。

    3. 选择 force 以在每次用户登录时更新用户数据。

    4. 选择 inherit 以使用在身份提供商中配置的同步模式。所有其他选项都将覆盖此同步模式。

  6. 映射器类型 列表中选择一个映射器。将鼠标悬停在 映射器类型 上以查看映射器的描述以及要为映射器输入的配置。

  7. 点击 保存

对于基于 JSON 的声明,您可以使用点表示法进行嵌套,并使用方括号按索引访问数组字段。例如,contact.address[0].country

要调查社交提供商提供的用户配置文件 JSON 数据的结构,您可以在启动服务器时启用 DEBUG 级别日志记录器 org.keycloak.social.user_profile_dump

可用的用户会话数据

在用户通过外部 IDP 登录后,Keycloak 会存储用户会话 note 数据,您可以访问这些数据。此数据可以使用令牌或 SAML 断言传播到请求登录的客户端,并通过适当的客户端映射器传递回客户端。

identity_provider

用于执行登录的代理的 IDP 别名。

identity_provider_identity

当前已认证用户的 IDP 用户名。通常(但不总是)与 Keycloak 用户名相同。例如,Keycloak 可以将用户 `john` 链接到 Facebook 用户 john123@gmail.com。在这种情况下,用户会话 note 的值是 john123@gmail.com

您可以使用类型为 User Session Note协议映射器 将此信息传播到您的客户端。

首次登录流程

当用户通过身份代理登录时,Keycloak 会导入用户的一些方面并将其链接到 realm 的本地数据库中。当 Keycloak 通过外部身份提供程序成功验证用户身份时,可能存在两种情况:

  • Keycloak 已经导入用户帐户并将其与已认证的身份提供程序帐户链接。在这种情况下,Keycloak 以现有用户身份进行身份验证,并重定向回应用程序。

  • Keycloak 中不存在此用户的帐户。通常,您会注册一个新帐户并将其导入到 Keycloak 数据库中,但也可能存在具有相同电子邮件地址的现有 Keycloak 帐户。自动将现有本地帐户链接到外部身份提供程序可能存在安全漏洞。您不能总是信任从外部身份提供程序获取的信息。

不同的组织在处理某些情况时有不同的要求。使用 Keycloak,您可以使用 IDP 设置中的 First Login Flow 选项,为首次从外部 IDP 登录的用户选择一个工作流。默认情况下,First Login Flow 选项指向 first broker login 流,但您可以为不同的身份提供程序使用您自己的流或不同的流。

该流位于管理控制台的身份验证选项卡下。当您选择 First Broker Login 流时,您会看到默认使用的身份验证器。您可以重新配置现有流。例如,您可以禁用某些身份验证器,将其中一些标记为 required,或配置某些身份验证器。

您还可以创建新的身份验证流,编写您自己的 Authenticator 实现,并在您的流中使用它。有关更多信息,请参阅服务器开发人员指南

默认首次登录流程身份验证器

审查个人资料
  • 此身份验证器显示个人资料信息页面,以便用户可以审查 Keycloak 从身份提供程序检索到的个人资料。

  • 您可以在操作菜单中设置 Update Profile On First Login 选项。

  • 当设置为 ON 时,用户将看到个人资料页面,请求提供更多信息以联合用户的身份。

  • 当设置为 missing 时,如果身份提供程序未提供强制性信息(例如电子邮件、名字或姓氏),则用户将看到个人资料页面。

  • 当设置为 OFF 时,除非用户在 Confirm Link Existing Account 身份验证器显示的页面中单击稍后阶段的 Review profile info 链接,否则不会显示个人资料页面。

如果唯一则创建用户

此身份验证器检查是否已存在与身份提供程序帐户具有相同电子邮件或用户名的 Keycloak 帐户。如果不存在,则身份验证器将创建一个新的本地 Keycloak 帐户,并将其与身份提供程序链接,整个流程完成。否则,它将转到下一个 Handle Existing Account 子流。如果您始终希望确保没有重复帐户,则可以将此身份验证器标记为 REQUIRED。在这种情况下,如果存在现有 Keycloak 帐户,用户将看到错误页面,并且用户需要通过帐户管理链接身份提供程序帐户。

  • 此身份验证器验证是否已存在与身份提供程序的帐户具有相同电子邮件或用户名的 Keycloak 帐户。

  • 如果帐户不存在,则身份验证器创建一个本地 Keycloak 帐户,将此帐户与身份提供程序链接,并终止流程。

  • 如果帐户存在,则身份验证器实现下一个 Handle Existing Account 子流。

  • 要确保没有重复帐户,您可以将此身份验证器标记为 REQUIRED。如果 Keycloak 帐户存在,用户将看到错误页面,并且用户必须通过帐户管理链接其身份提供程序帐户。

确认链接现有帐户
  • 在信息页面上,用户将看到一个具有相同电子邮件的 Keycloak 帐户。用户可以再次审查他们的个人资料,并使用不同的电子邮件或用户名。流程重新开始,并返回到 Review Profile 身份验证器。

  • 或者,用户可以确认他们想要将其身份提供程序帐户与其现有 Keycloak 帐户链接。

  • 如果您不希望用户看到此确认页面,并直接通过电子邮件验证或重新身份验证链接身份提供程序帐户,请禁用此身份验证器。

通过电子邮件验证现有帐户
  • 默认情况下,此身份验证器为 ALTERNATIVE。如果 realm 配置了 SMTP 设置,Keycloak 将使用此身份验证器。

  • 身份验证器会向用户发送电子邮件,以确认他们想要将身份提供程序与其 Keycloak 帐户链接。

  • 如果您不想通过电子邮件确认链接,而是希望用户使用密码重新身份验证,请禁用此身份验证器。

通过重新身份验证验证现有帐户
  • 如果电子邮件身份验证器不可用,请使用此身份验证器。例如,您尚未为您的 realm 配置 SMTP。此身份验证器会显示一个登录屏幕,供用户进行身份验证,以便将其 Keycloak 帐户与身份提供程序链接。

  • 用户还可以使用已链接到其 Keycloak 帐户的另一个身份提供程序重新进行身份验证。

  • 您可以强制用户使用 OTP。否则,它是可选的,并且在您为用户帐户设置了 OTP 时使用。

在用户可以使用任意用户名或电子邮件地址自行注册的通用环境中,AutoLink 身份验证器是危险的。除非您仔细管理用户注册并分配用户名和电子邮件地址,否则请勿使用此身份验证器。

要配置一个自动链接用户而无需提示的首次登录流程,请创建一个包含以下两个身份验证器的新流程:

如果唯一则创建用户

此身份验证器确保 Keycloak 处理唯一用户。将身份验证器要求设置为 Alternative

自动设置现有用户

此身份验证器在没有验证的情况下将现有用户设置为身份验证上下文。将身份验证器要求设置为“Alternative”。

此设置是可用的最简单设置,但可以使用其他身份验证器。例如:

  • 如果您希望最终用户确认其个人资料信息,则可以将“审查个人资料”身份验证器添加到流程的开头。

  • 您可以向此流程添加身份验证机制,强制用户验证其凭据。添加身份验证机制需要复杂的流程。例如,您可以将“自动设置现有用户”和“密码表单”设置为“Alternative”子流中的“Required”。

禁用自动用户创建

默认的首次登录流程会查找与外部身份匹配的 Keycloak 帐户,并提供链接它们的选项。如果不存在匹配的 Keycloak 帐户,则流程会自动创建一个。

对于某些设置,此默认行为可能不合适。一个示例是当您使用只读 LDAP 用户存储时,其中所有用户都是预先创建的。在这种情况下,您必须关闭自动用户创建。

要禁用用户创建:

步骤
  1. 点击菜单中的 身份验证

  2. 从列表中选择 First Broker Login

  3. Create User If Unique 设置为 DISABLED

  4. Confirm Link Existing Account 设置为 DISABLED

此配置还意味着 Keycloak 本身将无法确定哪个内部帐户对应于外部身份。因此,Verify Existing Account By Re-authentication 身份验证器将要求用户提供用户名和密码。

启用或禁用身份提供程序的用户创建完全独立于 realm 的 用户注册开关。您可以启用身份提供程序的用户创建,同时禁用 realm 登录设置中的用户自助注册,反之亦然。

检测现有用户首次登录流程

为了配置一个首次登录流程,其中:

  • 只有已在此 realm 中注册的用户才能登录,

  • 用户会被自动链接,而无需提示,

创建一个包含以下两个身份验证器的新流程:

检测现有代理用户

此身份验证器确保处理唯一用户。将身份验证器要求设置为 REQUIRED

自动设置现有用户

自动将现有用户设置为身份验证上下文,无需任何验证。将身份验证器要求设置为 REQUIRED

您必须将身份提供程序配置的 First Login Flow 设置为该流程。如果您想使用身份提供程序属性更新用户个人资料(姓氏、名字…),您也可以将 Sync Mode 设置为 force

如果您想将身份委托给其他身份提供程序(例如 GitHub、Facebook …),但又想管理哪些用户可以登录,则可以使用此流程。

使用此配置,Keycloak 无法确定哪个内部帐户对应于外部身份。Verify Existing Account By Re-authentication 身份验证器会要求提供程序提供用户名和密码。

当需要将另一个帐户链接到同一身份提供程序内的同一 Keycloak 帐户时,您可以配置以下身份验证器。

确认覆盖现有链接

此身份验证器将检测用户的现有代理链接,并显示一个确认页面以确认覆盖现有代理链接。将身份验证器要求设置为 REQUIRED。

此身份验证器的典型用途是以下场景:

  • 例如,考虑一个 Keycloak 用户 john,其电子邮件为 john@gmail.com。该用户链接到身份提供程序 google,其 google 用户名为 john@gmail.com

  • 然后,例如 Keycloak 用户 john 创建了一个新的 Google 帐户,电子邮件为 john-new@gmail.com

  • 然后在登录 Keycloak 期间,用户使用新的用户名(例如 john-new@gmail.com)向身份提供程序 google 进行了身份验证,该用户名尚未链接到任何 Keycloak 帐户(因为 Keycloak 帐户 john 仍然链接到 google 用户 john@gmail.com),因此触发了 first-broker-login 流程。

  • 在 first-broker-login 期间,Keycloak 用户 john 以某种方式通过身份验证(默认的 first-broker-login 重新身份验证,或者例如通过 Detect existing broker user 等身份验证器)。

  • 现在,通过身份验证流程中的此身份验证器,可以在用户 john 确认后,将 Keycloak 用户 johngoogle 身份提供程序链接覆盖为新的 google 用户 john-new@gmail.com 链接。

在创建包含此身份验证器的身份验证流程时,请确保在其他身份验证器已通过其他方式(通过重新身份验证或在上述 Detect existing broker user 之后)建立 Keycloak 用户之后添加此身份验证器。

登录后流程

当您希望在每次使用特定身份提供程序登录后触发一些额外的身份验证操作时,登录后流程非常有用。例如,您可能希望在每次 Keycloak 登录到 Facebook 后触发双因素身份验证,因为 Facebook 在其登录期间不提供双因素身份验证。

一旦您使用所需的步骤设置了身份验证流程,请在配置身份提供程序时将其设置为 Post login flow

登录后流程示例

在身份提供程序登录后请求双因素身份验证

最简单的方法是强制使用一种特定的双因素方法进行身份验证。例如,当请求 OTP 时,流程可以如下所示,仅配置一个身份验证器。当用户帐户上未设置 OTP 时,此类型的流程要求用户在首次使用身份提供程序登录期间配置 OTP。

带有 OTP 的 2FA 登录后流程

Post login OTP

更复杂的设置可以包括配置为 ALTERNATIVE 的多种双因素身份验证方法。在这种情况下,请确保如果用户尚未在其帐户上配置任何双因素身份验证,则会要求用户设置其中一种方法。这可以按如下方式完成:

  • 确保其中一种双因素方法在首次登录流程中配置为 REQUIRED。如果您期望所有用户都通过身份提供程序登录注册,则此方法可以工作。

  • 将双因素方法作为 ALTERNATIVE 包装到条件子流中,例如一个名为 2FA 的子流,并创建另一个条件子流,例如一个名为 OTP if no 2FA 的子流,该子流仅在前一个子流未执行时触发,并将要求用户添加一种双因素方法(例如,OTP)。类似的流程配置示例在身份验证流程章节的条件部分中提供。

为专用客户端请求额外的身份验证步骤

在某些情况下,客户端或客户端组可能需要在身份提供程序登录后执行一些额外的步骤。以下是一个流程示例,该流程规定,当请求客户端 scope foo 时,要求用户在身份提供程序登录后使用 OTP 进行身份验证。

带有客户端 scope 和 OTP 的 2FA 登录后流程

Post login with client scope and OTP

这是配置 Condition - client scope 以请求指定客户端范围的示例。

2FA 登录后流程客户端范围配置

Post login flow client scope configuration

请求的客户端需要在其上设置此客户端范围,可以设置为默认或可选。在后一种情况下,仅当客户端请求客户端范围时才执行流程(例如,在 OIDC/OAuth2 客户端登录的情况下,通过 scope 参数)。

检索外部 IDP 令牌

使用 Keycloak,您可以使用 IDP 设置页面上的 Store Token 配置选项来存储来自外部 IDP 身份验证过程的令牌和响应。

应用程序代码可以检索这些令牌和响应,以导入额外的用户信息或安全地请求外部 IDP。例如,应用程序可以使用 Google 令牌来使用其他 Google 服务和 REST API。要检索特定身份提供程序的令牌,请按如下方式发送请求

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

应用程序必须使用 Keycloak 进行身份验证并接收访问令牌。此访问令牌必须设置 broker 客户端级角色 read-token,因此用户必须具有此角色的角色映射,并且客户端应用程序必须在其范围内具有该角色。在这种情况下,由于您正在访问 Keycloak 中的受保护服务,请发送用户身份验证期间由 Keycloak 颁发的访问令牌。您可以通过将存储令牌可读开关设置为开启,在代理配置页面中将此角色分配给新导入的用户。

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

身份代理注销

注销时,Keycloak 会向最初用于登录的外部身份提供程序发送请求,并将用户从该身份提供程序中注销。

SSO 协议

本节讨论身份验证协议、Keycloak 身份验证服务器以及由 Keycloak 身份验证服务器保护的应用程序如何与这些协议交互。

OpenID Connect

OpenID Connect (OIDC) 是一种身份验证协议,它是 OAuth 2.0 的扩展。

OAuth 2.0 是一个用于构建授权协议的框架,并且是不完整的。然而,OIDC 是一种完整的身份验证和授权协议,它使用 Json Web Token (JWT) 标准。 JWT 标准定义了身份令牌 JSON 格式以及以紧凑且 Web 友好的方式对数据进行数字签名和加密的方法。

一般来说,OIDC 实现了两种用例。第一种情况是应用程序请求 Keycloak 服务器验证用户身份。成功登录后,应用程序会收到一个身份令牌和一个访问令牌身份令牌包含用户信息,包括用户名、电子邮件和个人资料信息。领域对访问令牌进行数字签名,其中包含访问信息(例如用户角色映射),应用程序使用这些信息来确定用户可以访问应用程序中的哪些资源。

第二种用例是客户端访问远程服务。

  • 客户端从 Keycloak 请求访问令牌,以代表用户调用远程服务。

  • Keycloak 验证用户身份,并征求用户同意授予对请求客户端的访问权限。

  • 客户端收到由领域数字签名的访问令牌

  • 客户端使用访问令牌对远程服务发出 REST 请求。

  • 远程 REST 服务提取访问令牌

  • 远程 REST 服务验证令牌签名。

  • 远程 REST 服务根据令牌内的访问信息,决定处理还是拒绝请求。

OIDC 身份验证流程

OIDC 有几种方法或流程,客户端或应用程序可以使用这些方法或流程来验证用户身份并接收身份访问令牌。该方法取决于请求访问的应用程序或客户端的类型。

授权码流程

授权码流程是一种基于浏览器的协议,适用于验证和授权基于浏览器的应用程序。它使用浏览器重定向来获取身份访问令牌。

  1. 用户使用浏览器连接到应用程序。应用程序检测到用户未登录到应用程序。

  2. 应用程序将浏览器重定向到 Keycloak 进行身份验证。

  3. 应用程序在浏览器重定向中传递回调 URL 作为查询参数。Keycloak 在成功身份验证后使用该参数。

  4. Keycloak 验证用户身份并创建一个一次性的、短期的临时代码。

  5. Keycloak 使用回调 URL 重定向到应用程序,并在回调 URL 中添加临时代码作为查询参数。

  6. 应用程序提取临时代码,并对 Keycloak 进行后台 REST 调用,以交换代码以获取身份访问以及刷新令牌。为了防止重放攻击,临时代码不能使用多次。

系统在令牌的生命周期内容易受到令牌被盗的攻击。出于安全和可扩展性原因,访问令牌通常设置为快速过期,以便后续令牌请求失败。如果令牌过期,应用程序可以使用登录协议发送的额外刷新令牌来获取新的访问令牌。

机密客户端在交换临时代码以获取令牌时提供客户端密钥。公共客户端不需要提供客户端密钥。当严格执行 HTTPS 并且为客户端注册的重定向 URI 受到严格控制时,公共客户端是安全的。 HTML5/JavaScript 客户端必须是公共客户端,因为没有办法安全地将客户端密钥传输到 HTML5/JavaScript 客户端。有关更多详细信息,请参阅 管理客户端 章节。

Keycloak 还支持 Proof Key for Code Exchange 规范。

隐式流程

隐式流程是一种基于浏览器的协议。它类似于授权码流程,但请求较少且没有刷新令牌。

当令牌通过重定向 URI 传输时,存在访问令牌在浏览器历史记录中泄漏的可能性(见下文)。

此外,此流程不为客户端提供刷新令牌。因此,访问令牌必须是长期有效的,或者用户必须在令牌过期时重新进行身份验证。

我们不建议使用此流程。支持此流程是因为它在 OIDC 和 OAuth 2.0 规范中。

该协议的工作方式如下

  1. 用户使用浏览器连接到应用程序。应用程序检测到用户未登录到应用程序。

  2. 应用程序将浏览器重定向到 Keycloak 进行身份验证。

  3. 应用程序在浏览器重定向中传递回调 URL 作为查询参数。Keycloak 在成功身份验证后使用该查询参数。

  4. Keycloak 验证用户身份并创建身份访问令牌。Keycloak 使用回调 URL 重定向到应用程序,并在回调 URL 中额外添加身份访问令牌作为查询参数。

  5. 应用程序从回调 URL 中提取身份访问令牌。

资源所有者密码凭据授权(直接访问授权)

直接访问授权供 REST 客户端使用,以代表用户获取令牌。它是一个包含以下内容的 HTTP POST 请求

  • 用户的凭据。凭据在表单参数中发送。

  • 客户端的 ID。

  • 客户端密钥(如果是机密客户端)。

HTTP 响应包含身份访问刷新令牌。

客户端凭据授权

客户端凭据授权基于与客户端关联的服务帐户的元数据和权限创建令牌,而不是获取代表外部用户工作的令牌。客户端凭据授权供 REST 客户端使用。

有关更多信息,请参阅 服务帐户 章节。

刷新令牌授权

默认情况下,Keycloak 在大多数流程的令牌响应中返回刷新令牌。一些例外情况是上面描述的隐式流程或客户端凭据授权。

刷新令牌与 SSO 浏览器会话的用户会话相关联,并且在用户会话的生命周期内有效。但是,客户端应至少每隔指定的时间间隔发送一次刷新令牌请求。否则,会话可能被视为“空闲”并可能过期。有关更多信息,请参阅 超时部分

Keycloak 支持 离线令牌,即使相应的浏览器 SSO 会话已过期,通常在客户端需要使用刷新令牌时也可以使用离线令牌。

刷新令牌轮换

可以指定刷新令牌一旦使用即被视为无效。这意味着客户端必须始终保存来自上次刷新响应的刷新令牌,因为 Keycloak 不再认为已使用的较旧的刷新令牌有效。这可以通过使用 超时部分中指定的撤销刷新令牌选项来设置。

Keycloak 还支持不存在刷新令牌轮换的情况。在这种情况下,刷新令牌在登录期间返回,但来自刷新令牌请求的后续响应将不会返回新的刷新令牌。例如,在 保护应用程序 部分的 FAPI 2 草案规范中推荐这种做法。在 Keycloak 中,可以使用 客户端策略 跳过刷新令牌轮换。您可以将执行器 suppress-refresh-token-rotation 添加到某些客户端配置文件,并配置客户端策略以指定将为哪些客户端触发配置文件,这意味着对于这些客户端,将跳过刷新令牌轮换。

设备授权授权

这由在输入功能有限或缺少合适浏览器的联网设备上运行的客户端使用。以下是该协议的简要概述

  1. 应用程序向 Keycloak 请求设备代码和用户代码。Keycloak 创建设备代码和用户代码。Keycloak 返回包含设备代码和用户代码的响应给应用程序。

  2. 应用程序向用户提供用户代码和验证 URI。用户访问验证 URI 以使用另一个浏览器进行身份验证。您可以定义一个简短的 verification_uri,它将被重定向到 Keycloak 验证 URI (/realms/realm_name/device) 在 Keycloak 外部 - 例如在代理中。

  3. 应用程序重复轮询 Keycloak,以查找用户是否完成用户授权。如果用户身份验证完成,应用程序将设备代码交换为身份访问刷新令牌。

客户端发起的后台通道身份验证授权

此功能供希望直接与 OpenID Provider 通信以启动身份验证流程的客户端使用,而无需像 OAuth 2.0 的授权码许可那样通过用户浏览器重定向。以下是该协议的简要概述

  1. 客户端向 Keycloak 请求一个 auth_req_id,用于标识客户端发出的身份验证请求。Keycloak 创建 auth_req_id。

  2. 收到此 auth_req_id 后,客户端需要重复轮询 Keycloak,以获取来自 Keycloak 的访问令牌、刷新令牌和 ID 令牌,以换取 auth_req_id,直到用户通过身份验证。

管理员可以将客户端发起的后台通道身份验证 (CIBA) 相关操作配置为每个 realm 的CIBA 策略

另请参阅 Keycloak 文档的其他位置,例如后台通道身份验证端点客户端发起的后台通道身份验证许可,位于安全应用部分。

CIBA 策略

管理员在 Admin Console 上执行以下操作

  • 打开Authentication → CIBA Policy选项卡。

  • 配置项目并单击Save

可配置的项目及其描述如下。

配置 描述

后台通道令牌传递模式

指定 CD(消费设备)如何获取身份验证结果和相关令牌。有三种模式:“poll”、“ping”和“push”。Keycloak 仅支持“poll”。默认设置为“poll”。此配置是必需的。有关更多详细信息,请参阅 CIBA 规范

过期时间

“auth_req_id”的过期时间,单位为秒,自收到身份验证请求起算。默认设置为 120 秒。此配置是必需的。有关更多详细信息,请参阅 CIBA 规范

间隔

CD(消费设备)在轮询令牌端点请求之间需要等待的间隔,单位为秒。默认设置为 5 秒。此配置是可选的。有关更多详细信息,请参阅 CIBA 规范

请求身份验证的用户提示

识别正在请求身份验证的终端用户的方式。默认设置为“login_hint”。有三种模式:“login_hint”、“login_hint_token”和“id_token_hint”。Keycloak 仅支持“login_hint”。此配置是必需的。有关更多详细信息,请参阅 CIBA 规范

提供程序设置

CIBA 许可使用以下两个提供程序。

  1. 身份验证通道提供程序:提供 Keycloak 与实际通过 AD(身份验证设备)验证用户的实体之间的通信。

  2. 用户解析器提供程序:从客户端提供的信息中获取 Keycloak 的 UserModel,以识别用户。

Keycloak 具有默认提供程序。但是,管理员需要像这样设置身份验证通道提供程序

kc.[sh|bat] start --spi-ciba-auth-channel-ciba-http-auth-channel-http-authentication-channel-uri=https://backend.internal.example.com

可配置的项目及其描述如下。

配置 描述

http-authentication-channel-uri

指定实际通过 AD(身份验证设备)验证用户的实体的 URI。

身份验证通道提供程序

CIBA 标准文档未指定如何通过 AD 验证用户。因此,它可能根据产品的判断来实施。Keycloak 将此身份验证委托给外部身份验证实体。为了与身份验证实体通信,Keycloak 提供了身份验证通道提供程序。

Keycloak 的实现假定身份验证实体受 Keycloak 管理员的控制,以便 Keycloak 信任该身份验证实体。不建议使用 Keycloak 管理员无法控制的身份验证实体。

身份验证通道提供程序作为 SPI 提供程序提供,以便 Keycloak 用户可以实施自己的提供程序以满足其环境。Keycloak 提供了其默认提供程序,称为 HTTP 身份验证通道提供程序,该提供程序使用 HTTP 与身份验证实体进行通信。

如果 Keycloak 用户想要使用 HTTP 身份验证通道提供程序,他们需要了解 Keycloak 和身份验证实体之间的合同,该合同由以下两个部分组成。

身份验证委托请求/响应

Keycloak 向身份验证实体发送身份验证请求。

身份验证结果通知/确认

身份验证实体将身份验证结果通知给 Keycloak。

身份验证委托请求/响应由以下消息组成。

身份验证委托请求

该请求从 Keycloak 发送到身份验证实体,以请求其通过 AD 进行用户身份验证。

POST [delegation_reception]
  • 标头

名称 描述

Content-Type

application/json

消息体为 json 格式。

Authorization

Bearer [token]

[token] 在身份验证实体将身份验证结果通知给 Keycloak 时使用。

  • 参数

类型 名称 描述

路径

delegation_reception

身份验证实体提供的用于接收委托请求的端点

  • 主体

名称 描述

login_hint

它告诉身份验证实体谁通过 AD 进行了身份验证。
默认情况下,它是用户的“用户名”。
此字段为必填字段,由 CIBA 标准文档定义。

scope

它告诉身份验证实体从经过身份验证的用户那里获得哪些 scope 的同意。
此字段为必填字段,由 CIBA 标准文档定义。

is_consent_required

它显示身份验证实体是否需要获得经过身份验证的用户关于 scope 的同意。
此字段为必填字段。

binding_message

其值旨在同时显示在 CD 和 AD 的 UI 中,以使用户认识到 AD 的身份验证是由 CD 触发的。
此字段为可选字段,由 CIBA 标准文档定义。

acr_values

它告诉来自 CD 的请求身份验证上下文类引用。
此字段为可选字段,由 CIBA 标准文档定义。

身份验证委托响应

响应从身份验证实体返回到 Keycloak,以通知身份验证实体已收到来自 Keycloak 的身份验证请求。

  • 响应

HTTP 状态代码 描述

201

它通知 Keycloak 收到身份验证委托请求。

身份验证结果通知/确认由以下消息组成。

身份验证结果通知

身份验证实体将身份验证请求的结果发送到 Keycloak。

POST /realms/[realm]/protocol/openid-connect/ext/ciba/auth/callback
  • 标头

名称 描述

Content-Type

application/json

消息体为 json 格式。

Authorization

Bearer [token]

[token] 必须是身份验证实体在身份验证委托请求中从 Keycloak 收到的令牌。

  • 参数

类型 名称 描述

路径

realm

Realm 名称

  • 主体

名称 描述

status

它告诉通过 AD 进行用户身份验证的结果。
它必须是以下状态之一。
SUCCEED:通过 AD 的身份验证已成功完成。
UNAUTHORIZED:通过 AD 的身份验证未完成。
CANCELLED:通过 AD 的身份验证已被用户取消。

身份验证结果确认

响应从 Keycloak 返回到身份验证实体,以通知 Keycloak 已收到来自身份验证实体的用户身份验证结果。

  • 响应

HTTP 状态代码 描述

200

它通知身份验证实体收到身份验证结果的通知。

用户解析器提供程序

即使是同一用户,其表示形式在每个 CD、Keycloak 和身份验证实体中也可能有所不同。

为了使 CD、Keycloak 和身份验证实体识别同一用户,此用户解析器提供程序在它们之间转换其自身的用户表示形式。

用户解析器提供程序作为 SPI 提供程序提供,以便 Keycloak 用户可以实施自己的提供程序以满足其环境。Keycloak 提供了其默认提供程序,称为默认用户解析器提供程序,它具有以下特点。

  • 仅支持 login_hint 参数,并用作默认值。

  • Keycloak 中的 UserModel 的 username 用于表示 CD、Keycloak 和身份验证实体上的用户。

OIDC 注销

OIDC 有四个与注销机制相关的规范

同样,由于所有这些都在 OIDC 规范中描述,因此我们在此处仅给出简要概述。

会话管理

这是基于浏览器的注销。应用程序定期从 Keycloak 获取会话状态信息。当 Keycloak 上的会话终止时,应用程序将注意到并触发其自身的注销。

RP 发起的注销

这也是基于浏览器的注销,其中注销通过将用户重定向到 Keycloak 上的特定端点开始。当用户单击某些应用程序页面上的Log Out链接时,通常会发生此重定向,该应用程序先前使用 Keycloak 对用户进行身份验证。

一旦用户被重定向到注销端点,Keycloak 将向客户端发送注销请求,以使它们使其本地用户会话无效,并可能在注销过程完成后将用户重定向到某个 URL。如果未使用 id_token_hint 参数,则可能会选择性地请求用户确认注销。注销后,只要提供了 post_logout_redirect_uri 作为参数,用户就会自动重定向到指定的 post_logout_redirect_uri。请注意,如果包含 post_logout_redirect_uri,则需要包含 client_idid_token_hint 参数。此外,post_logout_redirect_uri 参数需要与客户端配置中指定的 Valid Post Logout Redirect URIs 之一匹配。

根据客户端配置,可以通过前端通道或后台通道将注销请求发送到客户端。对于依赖于上一节中描述的会话管理的前端浏览器客户端,Keycloak 不需要向它们发送任何注销请求;这些客户端会自动检测到浏览器中的 SSO 会话已注销。

前端通道注销

要配置客户端以通过前端通道接收注销请求,请查看前端通道注销客户端设置。使用此方法时,请考虑以下事项

  • Keycloak 发送到客户端的注销请求依赖于浏览器和为注销页面呈现的嵌入式 iframes

  • 由于基于 iframes,前端通道注销可能会受到内容安全策略 (CSP) 的影响,并且注销请求可能会被阻止。

  • 如果用户在呈现注销页面之前或在实际将注销请求发送到客户端之前关闭浏览器,则他们在客户端的会话可能不会失效。

考虑使用后台通道注销,因为它提供了一种更可靠和安全的方法来注销用户并终止他们在客户端上的会话。

如果客户端未启用前端通道注销,则 Keycloak 将首先尝试通过后台通道使用后台通道注销 URL发送注销请求。如果未定义,服务器将回退到使用管理 URL

后台通道注销

这是一种非基于浏览器的注销,它使用 Keycloak 和客户端之间的直接后台通道通信。Keycloak 向所有登录到 Keycloak 的客户端发送包含注销令牌的 HTTP POST 请求。这些请求被发送到 Keycloak 上注册的后台通道注销 URL,并且应该触发客户端侧的注销。

Keycloak 服务器 OIDC URI 端点

以下是 Keycloak 发布的 OIDC 端点列表。当非 Keycloak 客户端适配器使用 OIDC 与身份验证服务器通信时,可以使用这些端点。它们都是相对 URL。URL 的根由 HTTP(S) 协议、主机名以及可选路径组成:例如

https://#:8080
/realms/{realm-name}/protocol/openid-connect/auth

用于在授权码流程中获取临时代码,或使用隐式流程、直接许可或客户端许可获取令牌。

/realms/{realm-name}/protocol/openid-connect/token

授权码流程用于将临时代码转换为令牌。

/realms/{realm-name}/protocol/openid-connect/logout

用于执行注销。

/realms/{realm-name}/protocol/openid-connect/userinfo

用于 OIDC 规范中描述的用户信息服务。

/realms/{realm-name}/protocol/openid-connect/revoke

用于 RFC7009 中描述的 OAuth 2.0 令牌撤销。

/realms/{realm-name}/protocol/openid-connect/certs

用于 JSON Web 密钥集 (JWKS),其中包含用于验证任何 JSON Web 令牌 (jwks_uri) 的公钥

/realms/{realm-name}/protocol/openid-connect/auth/device

用于设备授权许可,以获取设备代码和用户代码。

/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth

这是客户端发起的后台通道身份验证许可的 URL 端点,用于获取 auth_req_id,该 ID 标识客户端发出的身份验证请求。

/realms/{realm-name}/protocol/openid-connect/logout/backchannel-logout

这是用于执行 OIDC 规范中描述的后台通道注销的 URL 端点。

在所有这些中,将 {realm-name} 替换为 realm 的名称。

SAML

SAML 2.0 与 OIDC 类似,但更加成熟。它源于 SOAP 和 Web 服务消息规范,因此通常比 OIDC 更为冗长。SAML 2.0 是一种身份验证协议,用于在身份验证服务器和应用程序之间交换 XML 文档。XML 签名和加密用于验证请求和响应。

总的来说,SAML 实现了两种用例。

第一种用例是应用程序请求 Keycloak 服务器验证用户身份。成功登录后,应用程序将收到一个 XML 文档。该文档包含一个 SAML 断言,其中指定了用户属性。Realm 对文档进行数字签名,其中包含访问信息(例如用户角色映射),应用程序使用这些信息来确定用户被允许访问应用程序中的哪些资源。

第二种用例是客户端访问远程服务。客户端从 Keycloak 请求 SAML 断言,以代表用户调用远程服务。

SAML 绑定

Keycloak 支持三种绑定类型。

重定向绑定

重定向绑定使用一系列浏览器重定向 URI 来交换信息。

  1. 用户使用浏览器连接到应用程序。应用程序检测到用户未通过身份验证。

  2. 应用程序生成一个 XML 身份验证请求文档,并将其编码为 URI 中的查询参数。该 URI 用于重定向到 Keycloak 服务器。根据您的设置,应用程序还可以对 XML 文档进行数字签名,并将签名作为查询参数包含在重定向到 Keycloak 的 URI 中。此签名用于验证发送请求的客户端。

  3. 浏览器重定向到 Keycloak。

  4. 服务器提取 XML 身份验证请求文档,并验证数字签名(如果需要)。

  5. 用户输入其身份验证凭据。

  6. 身份验证后,服务器生成一个 XML 身份验证响应文档。该文档包含一个 SAML 断言,其中包含有关用户的元数据,包括姓名、地址、电子邮件以及用户拥有的任何角色映射。该文档通常使用 XML 签名进行数字签名,并且也可能被加密。

  7. XML 身份验证响应文档被编码为重定向 URI 中的查询参数。该 URI 将浏览器带回应用程序。数字签名也作为查询参数包含在内。

  8. 应用程序接收重定向 URI 并提取 XML 文档。

  9. 应用程序验证 realm 的签名,以确保它收到有效的身份验证响应。SAML 断言中的信息用于做出访问决策或显示用户数据。

POST 绑定

POST 绑定与 重定向 绑定类似,但 POST 绑定使用 POST 请求而不是 GET 请求来交换 XML 文档。POST 绑定使用 JavaScript 使浏览器在交换文档时向 Keycloak 服务器或应用程序发送 POST 请求。HTTP 响应一个 HTML 文档,其中包含一个包含嵌入式 JavaScript 的 HTML 表单。当页面加载时,JavaScript 会自动调用该表单。

推荐使用 POST 绑定,原因在于以下两个限制:

  • 安全性 — 使用 重定向 绑定时,SAML 响应是 URL 的一部分。由于可以在日志中捕获响应,因此安全性较低。

  • 大小 — 在 HTTP 有效负载中发送文档比在有限的 URL 中为大量数据提供了更大的空间。

ECP

增强型客户端或代理 (ECP) 是一种 SAML v.2.0 配置文件,允许在 Web 浏览器上下文之外交换 SAML 属性。它通常由基于 REST 或 SOAP 的客户端使用。

Keycloak 服务器 SAML URI 端点

Keycloak 为所有 SAML 请求提供一个端点。

http(s)://authserver.host/realms/{realm-name}/protocol/saml

所有绑定都使用此端点。

OpenID Connect 与 SAML 的比较

以下列出了一些在选择协议时需要考虑的因素。

对于大多数用途,Keycloak 建议使用 OIDC。

OIDC

  • OIDC 专门设计用于 Web。

  • OIDC 适用于 HTML5/JavaScript 应用程序,因为它比 SAML 更容易在客户端实现。

  • OIDC 令牌采用 JSON 格式,这使得 Javascript 更容易使用它们。

  • OIDC 具有使安全实施更轻松的功能。例如,请参阅规范用于确定用户登录状态的 iframe 技巧

SAML

  • SAML 被设计为在 Web 之上工作的层。

  • SAML 可能比 OIDC 更为冗长。

  • 用户选择 SAML 而不是 OIDC,因为人们普遍认为 SAML 更成熟。

  • 用户选择 SAML 而不是 OIDC,因为现有应用程序已使用 SAML 进行安全保护。

Docker 注册表 v2 身份验证

Docker 身份验证默认情况下处于禁用状态。要启用 Docker 身份验证,请参阅《启用和禁用功能》指南。

Docker 注册表 V2 身份验证是一种协议,类似于 OIDC,用于针对 Docker 注册表验证用户身份。Keycloak 对此协议的实现使 Docker 客户端可以使用 Keycloak 身份验证服务器针对注册表进行身份验证。此协议使用标准令牌和签名机制,但它确实偏离了真正的 OIDC 实现。它的偏差在于为请求和响应使用了非常特定的 JSON 格式,并将存储库名称和权限映射到 OAuth 范围机制。

Docker 身份验证流程

身份验证流程在 Docker API 文档中进行了描述。以下是从 Keycloak 身份验证服务器的角度进行的摘要

  • 执行 docker login

  • Docker 客户端从 Docker 注册表请求资源。如果资源受到保护且请求中没有身份验证令牌,则 Docker 注册表服务器会响应 401 HTTP 消息,其中包含有关所需权限和授权服务器位置的一些信息。

  • Docker 客户端基于 Docker 注册表的 401 HTTP 消息构建身份验证请求。客户端使用本地缓存的凭据(来自 docker login 命令)作为 HTTP 基本身份验证 请求的一部分发送到 Keycloak 身份验证服务器。

  • Keycloak 身份验证服务器尝试验证用户身份,并返回包含 OAuth 风格 Bearer 令牌的 JSON 正文。

  • Docker 客户端从 JSON 响应中接收到 bearer 令牌,并在授权标头中使用它来请求受保护的资源。

  • Docker 注册表接收到来自 Keycloak 服务器的带有令牌的对受保护资源的新请求。注册表验证令牌,并授予对请求资源的访问权限(如果适用)。

使用 Docker 协议成功进行身份验证后,Keycloak 不会创建浏览器 SSO 会话。浏览器 SSO 会话不使用 Docker 协议,因为它无法刷新令牌或从 Keycloak 服务器获取令牌或会话的状态;因此,浏览器 SSO 会话不是必需的。有关更多详细信息,请参阅“瞬态会话”部分。

Keycloak Docker 注册表 v2 身份验证服务器 URI 端点

Keycloak 为所有 Docker auth v2 请求提供一个端点。

http(s)://authserver.host/realms/{realm-name}/protocol/docker-v2/auth

管理对 realm 资源的访问

在 Keycloak 上创建的每个 realm 都有一个专用的管理控制台,可以从中管理该 realm。“master” realm 是一个特殊的 realm,允许管理员管理系统上的多个 realm。您还可以为不同 realm 中的用户定义细粒度的访问权限,以管理服务器。本章将介绍所有这些场景。

Master realm 访问控制

Keycloak 中的 master realm 是一个特殊的 realm,与其他 realm 的处理方式不同。Keycloak master realm 中的用户可以被授予管理部署在 Keycloak 服务器上的零个或多个 realm 的权限。创建 realm 时,Keycloak 会自动创建各种角色,这些角色授予访问该新 realm 的权限。可以通过将这些角色映射到 master realm 中的用户来控制对管理控制台和管理 REST 端点的访问。可以创建多个超级用户,以及只能管理特定 realm 的用户。

全局角色

master realm 中有两个 realm 级别的角色。它们是:

  • admin

  • create-realm

具有 admin 角色的用户是超级用户,并且拥有管理服务器上任何 realm 的完全访问权限。具有 create-realm 角色的用户被允许创建新的 realm。他们将被授予对其创建的任何新 realm 的完全访问权限。

Realm 特定角色

master realm 中的管理员用户可以被授予对系统中一个或多个其他 realm 的管理权限。Keycloak 中的每个 realm 都由 master realm 中的一个客户端表示。客户端的名称是 <realm name>-realm。这些客户端各自定义了客户端级别的角色,这些角色定义了管理单个 realm 的不同级别的访问权限。

可用的角色包括:

  • create-client

  • impersonation

  • manage-authorization

  • manage-clients

  • manage-events

  • manage-identity-providers

  • manage-realm

  • manage-users

  • query-clients

  • query-groups

  • query-realms

  • query-users

  • view-authorization

  • view-clients

  • view-events

  • view-identity-providers

  • view-realm

  • view-users

将您想要的角色分配给您的用户,他们将只能使用管理控制台的特定部分。

具有 manage-users 角色的管理员将只能将他们自己拥有的管理员角色分配给用户。因此,如果管理员拥有 manage-users 角色但没有 manage-realm 角色,他们将无法分配 manage-realm 角色。

专用 realm 管理控制台

每个 realm 都有一个专用的管理控制台,可以通过访问 URL /admin/{realm-name}/console 来访问。可以通过分配特定的用户角色映射,向该 realm 中的用户授予 realm 管理权限。

每个 realm 都有一个名为 realm-management 的内置客户端。您可以通过转到 realm 的“客户端”左侧菜单项来查看此客户端。此客户端定义了客户端级别的角色,这些角色指定了可以授予的管理 realm 的权限。

  • create-client

  • impersonation

  • manage-authorization

  • manage-clients

  • manage-events

  • manage-identity-providers

  • manage-realm

  • manage-users

  • query-clients

  • query-groups

  • query-realms

  • query-users

  • realm-admin

  • view-authorization

  • view-clients

  • view-events

  • view-identity-providers

  • view-realm

  • view-users

将您想要的角色分配给您的用户,他们将只能使用管理控制台的特定部分。

使用权限委派 realm 管理

您可以使用细粒度管理员权限功能将域管理委派给其他管理员,即域管理员。与通过全局和域特定角色提供的基于角色的访问控制 (RBAC) 机制不同,此功能基于一组明确定义的可对其执行的操作,提供对如何访问和管理域资源更细粒度的控制。

通过依赖于基于策略的访问控制,服务器管理员可以使用不同的策略类型或访问控制方法来定义对域资源的权限,例如用户、组和客户端,以便将域管理员限制为仅访问域资源及其操作的子集。

此功能提供了上述 RBAC 机制的替代方案,但它不会取代它。您仍然可以授予管理角色,例如 view-usersmanage-clients,以委派对域管理员的访问权限,但这样做将跳过此功能提供的机制。

仅当通过管理控制台或 Admin API 管理资源时,才强制执行对域资源的访问。

了解域资源类型

在一个域中,您可以管理不同类型的资源,例如用户、组、客户端、客户端作用域、角色等等。作为域管理员,您在管理身份以及他们如何进行身份验证和授权以访问域和应用程序时,始终在管理这些资源。

此功能提供了必要的机制来强制执行在管理域资源时的访问控制,仅限于

  • 用户

  • 客户端

  • 角色

您可以管理给定资源类型的所有资源的权限,例如域中的所有用户,或者管理特定域资源的权限,例如域中的特定用户或一组用户。

了解访问作用域

每个域资源都支持一组明确定义的管理操作或作用域,可以对其执行这些操作,例如 viewmanage 以及特定于资源的操作,例如 view-members(如果您以组为例)。

管理权限时,您要从资源类型中选择一组或多个作用域,以允许域管理员对资源类型执行特定操作。例如,授予 view 作用域将使域管理员能够列出、搜索和查看域资源。另一方面,manage 作用域将允许管理员对其执行更新和删除操作。

这些作用域彼此完全独立。如果您授予 manage 域资源的访问权限,这并不意味着会自动授予 view 作用域。作用域之间不存在传递依赖关系。尽管这可能会影响管理权限时的整体用户体验,因为您需要选择单个作用域,但好处是您可以更轻松地识别强制执行对特定作用域访问的权限。

来自资源类型的某些作用域与来自另一个资源类型的作用域具有关系(不是传递依赖关系)。当您管理代表一组域资源的资源类型时,例如域组及其成员,这种关系主要是正确的。

用户资源类型

用户域资源类型表示域中的用户。您可以根据以下一组作用域管理用户的权限

作用域 描述 也通过以下方式授予

view

定义域管理员是否可以查看用户。每当您想要

view-members 使查询可以使用用户时,都应设置此作用域。

manage

定义域管理员是否可以管理用户。

manage-members

manage-group-membership

定义域管理员是否可以将用户分配到/从组中取消分配。

None

map-roles

定义域管理员是否可以将角色分配到/从用户取消分配。

None

impersonate

定义域管理员是否可以模拟其他用户。

impersonate-members

用户资源类型与您可以为组设置的某些权限具有很强的关系。大多数时候,用户是组成员,并且授予对组的 view-membersmanage-members 的访问权限也应该允许域管理员 viewmanage 该组的成员。

此功能不支持强制执行对联合资源的访问,但是,未来改进正在考虑此限制。

组资源类型

域资源类型表示域中的组。您可以根据以下一组管理操作管理组的权限

操作 描述

view

定义域管理员是否可以查看组。每当您想要使查询可以使用组时,都应设置此作用域。

manage

定义域管理员是否可以管理组。

view-members

定义域管理员是否可以查看组成员。此操作适用于组层次结构中的任何子组。可以通过显式拒绝特定子组的权限来阻止这种情况。

manage-members

定义域管理员是否可以管理组成员。此操作适用于组层次结构中的任何子组。可以通过显式拒绝特定子组的权限来阻止这种情况。

impersonate-members

定义域管理员是否可以模拟组成员。此操作适用于组层次结构中的任何子组。可以通过显式拒绝特定子组的权限来阻止这种情况。

manage-membership

定义域管理员是否可以从组中添加或删除成员。

客户端资源类型

客户端域资源类型表示域中的客户端。您可以根据以下一组管理操作管理客户端的权限

操作 描述

view

定义域管理员是否可以查看客户端。每当您想要使查询可以使用客户端时,都应设置此作用域。

manage

定义域管理员是否可以管理客户端。

map-roles

定义域管理员是否可以将客户端定义的任何角色分配给用户。

map-roles-composite

定义域管理员是否可以将客户端定义的任何角色作为复合角色分配给另一个角色。

map-roles-client-scope

定义域管理员是否可以将客户端定义的任何角色分配给客户端作用域。

map-roles 操作不授予管理用户或任意分配角色的能力。管理员还必须具有用户的用户角色映射权限。

角色资源类型

角色域资源类型表示域中的角色。您可以根据以下一组管理操作管理角色的权限

操作 描述

map-role

定义域管理员是否可以将一个角色(或多个角色)分配给用户。

map-role-composite

定义域管理员是否可以将一个角色(或多个角色)作为复合角色分配给另一个角色。

map-role-client-scope

定义域管理员是否可以将一个角色(或多个角色)应用于客户端作用域。

map-roles 操作不授予管理用户或任意分配角色的能力。管理员还必须具有用户的用户角色映射权限。

如果客户端资源类型权限具有 map-rolesmap-roles-compositemap-roles-client-scope 作用域,则如果角色是客户端角色,它将优先于任何角色资源类型权限。

为域启用管理员权限

要在域中启用细粒度管理员权限,请按照以下步骤操作

  • 登录到管理控制台。

  • 点击 Realm 设置

  • 启用 Admin Permissions 并单击 Save

Fine grain enable

启用后,管理控制台的左侧菜单中会出现 Permissions 部分。

Fine grain permissions tab

从此部分,您可以管理域资源的权限。

管理权限

Permissions 选项卡提供了域内所有活动权限的概述。从这里,管理员可以创建、更新、删除或搜索权限。您还可以预先评估您创建的权限,以检查它们是否按预期强制执行对域资源的访问。有关更多详细信息,请参阅评估权限

要创建权限,请单击 Create permission 按钮并选择要保护的资源类型。

Selecting a resource type to protect

选择资源类型后,您现在可以定义应如何为所选类型的一个或多个资源集强制执行访问

Creating a permission

管理权限时,您可以定义以下设置

  • 名称:权限的唯一名称。该名称也不应与任何策略名称冲突

  • 描述:可选描述,用于更好地描述权限的用途

  • 授权作用域:一组或多个作用域,表示您要为所选资源类型保护的操作。管理员必须为每个操作分配显式权限才能执行相应的操作。例如,仅分配 manage 而不分配 view 将阻止用户可见。

  • 强制访问:定义权限应强制访问所选类型的所有资源还是域中的特定资源。

  • 策略:定义一组或多个策略,应评估这些策略以授予或拒绝访问所选资源。

创建权限后,它将在强制访问您选择的(所有)资源和作用域时自动生效。在生产环境中创建和更新权限时,请记住这一事实。

定义查看域资源的权限

此功能依赖于部分评估机制,以部分评估域管理员在列出和查看域资源时拥有的权限。此机制将预取为与查看相关的作用域设置的所有权限,其中直接或间接地引用了域管理员。

授予访问权限以 view 某种类型的域资源的权限必须使用以下策略之一,以使其可用于查询

  • 用户

  • 角色

通过使用上述任何策略,Keycloak 可以通过查找对域管理员的直接引用(如果使用用户策略)或间接引用(如果使用角色或组策略)来预先计算域管理员可以查看的资源集。因此,部分评估机制涉及使用将在数据库级别运行的访问控制来修饰查询。此功能主要对于正确允许分页资源以及避免在服务器端评估查询返回的每个域资源的权限时产生额外的开销非常重要。

仅当为域启用该功能,并且用户未被授予与查看相关的管理角色(例如 view-usersview-clients)时,才会发生部分评估和过滤。例如,对于被授予 admin 角色的常规服务器管理员,它不会发生。

查询资源时,部分评估机制的工作方式如下

  • 解析引用域管理员的特定资源类型的所有权限

  • 预先评估每个权限,以检查域管理员是否具有对与该权限关联的资源的访问权限

  • 根据授予或拒绝的资源修饰数据库查询

因此,查询的结果集将仅包含域管理员有权访问任何与查看相关的作用域的域资源。

搜索权限

Admin Console 提供了几种搜索权限的方法,支持以下功能

  • 搜索在其 名称 中包含特定字符串的权限

  • 搜索特定资源类型的权限,例如 用户

  • 搜索应用于特定资源的特定资源类型的权限(例如用户 myadmin用户 资源类型)。

  • 搜索具有给定作用域的特定资源类型的权限(例如具有 manage 作用域的 用户 资源类型权限)。

  • 搜索应用于特定资源且具有特定作用域的特定资源类型的权限(例如用户 myadmin 的具有 manage 作用域的 用户 资源类型权限)。

细粒度权限搜索

Fine grained permissions search

这些功能允许服务器管理员对其权限范围执行查询,并识别哪些权限正在强制执行对一组或多个域资源及其作用域的访问。结合 Evaluation 选项卡上的评估工具,它们为管理域中的权限提供了关键的管理工具。有关更多详细信息,请参阅评估权限

管理策略

Policies 选项卡允许管理员使用不同的访问控制方法定义条件,以确定是否应将权限授予尝试对域资源执行操作的管理员。管理权限时,您必须至少关联一个策略才能授予或拒绝访问域资源。

策略基本上是评估为 GRANTDENY 的条件。它们的结果将决定是否应授予或拒绝权限。

仅当其所有关联策略都评估为 GRANT 时,才授予权限。否则,权限将被拒绝,并且域管理员将无法访问受保护的资源。

Keycloak 提供了一组内置策略,您可以从中选择

Selecting a policy type

一旦您为您的域定义了良好且稳定的权限模型,就几乎不需要创建策略。您可以改为重用现有策略来创建更多权限。

有关每种策略类型的更多详细信息,请参阅管理策略

评估权限

Evaluation 选项卡提供了一个测试环境,管理员可以在其中验证权限是否按预期强制执行访问。管理员可以看到在强制访问特定资源时涉及哪些权限以及结果是什么。

您需要提供一组字段才能运行评估

  • 用户,域管理员或尝试访问资源的主体

  • 资源类型,您要评估的资源类型

  • 资源选择器,根据所选的 资源类型,系统将提示您选择特定的域资源,例如用户、组或客户端。

  • 授权作用域,您要评估的作用域或操作。如果未提供,则评估将针对所选资源类型的所有作用域进行。

细粒度权限评估选项卡

Fine grained permissions evaluation tab

通过单击 Evaluate 按钮,服务器将评估与所选资源和作用域关联的所有权限,就像所选 用户 在使用管理控制台或 Admin API 时尝试访问资源一样。

例如,在上面的示例中,您可以看到用户 myadmin 可以 manage 用户 user-1,因为 Allow managing all realm users 权限投票为 PERMIT,因此授予了对 manage 作用域的访问权限。但是,所有其他作用域都被拒绝。

结合 Permissions 选项卡中的搜索功能,您可以执行故障排除以识别任何未按预期运行的权限。

评估权限时,以下规则适用

  • 特定于资源的权限的结果优先于授予对某种类型的所有资源访问权限的更广泛的权限

  • 如果特定资源不存在权限,则将根据授予对某种类型的所有资源访问权限的权限来授予访问权限

  • 强制访问特定资源的不同权限的结果仅当它们都允许访问该资源时才授予访问权限

解决冲突的权限

权限可以关联多个策略。随着授权模型的演进,权限内的一些策略,甚至与特定资源相关的不同权限之间,常常会发生冲突。

只要任何权限评估为“拒绝”,评估结果都将为“拒绝”。 如果存在与同一资源相关的多个权限,则所有权限都必须授予访问权限,结果才会是“授予”。

细粒度的管理员权限允许您为单个资源或资源类型本身(例如所有用户、所有组等)设置权限。 如果存在与特定资源相关的权限,则在评估期间将考虑“所有资源”权限。 如果不存在特定权限,则回退到“所有资源”权限。 这种方法有助于解决以下场景:例如,允许 realm-admins 组的成员管理 realm 组成员,但阻止他们管理 realm-admins 组本身的成员。

以 Realm 管理员身份访问 Realm 管理控制台

Realm 管理员可以访问专用的 realm 特定管理控制台,该控制台允许他们管理其分配的 realm 内的资源。 此控制台与主 Keycloak 管理控制台分开,后者通常由服务器管理员使用。

有关专用 realm 管理控制台和可用角色的更多详细信息,请参阅: 专用管理控制台

要访问管理控制台,realm 管理员必须至少分配有以下角色之一,具体取决于他们需要管理的资源

  • query-users – 查询 realm 用户是必需的。

  • query-groups – 查询 realm 组是必需的。

  • query-clients – 查询 realm 客户端是必需的。

通过向 realm 用户授予任何这些角色,他们将能够访问管理控制台,但仅限于与授予的角色对应的区域。 例如,如果您分配 query-users 角色,则 realm 管理员将只能访问管理控制台中的“用户”部分。 如果管理员负责多种资源类型(例如用户和组),他们必须分配所有相应的“query-*”角色。

这些角色启用对查询资源的基本访问权限,但不授予查看或修改它们的权限。 要授予或拒绝访问 realm 资源,您需要为每种资源类型提供的任何操作设置权限。 有关更多详细信息,请参阅管理权限

角色和权限关系

细粒度权限用于授予额外的权限。 您无法覆盖内置管理员角色的默认行为。 如果向 realm 管理员分配了一个或多个管理员角色,则会阻止评估权限。 这意味着,如果向 realm 管理员分配了相应的管理员角色,则将绕过权限评估,并授予访问权限。

管理员角色 描述

query-users

realm 管理员可以在管理控制台中看到“用户”部分,并且可以在 realm 中搜索用户。 这不授予查看用户的能力。

query-groups

realm 管理员可以在管理控制台中看到“”部分,并且可以在 realm 中搜索组。 这不授予查看组的能力。

query-clients

realm 管理员可以在管理控制台中看到“客户端”部分,并且可以在 realm 中搜索客户端。 这不授予查看客户端的能力。

view-users

realm 管理员可以查看 realm 中的所有用户和组。

manage-users

realm 管理员可以查看map-rolesmanage-group-membershipmanage realm 中的所有用户,以及查看manage-membershipmanage realm 中的组。

impersonation

realm 管理员可以模拟 realm 中的所有用户。

view-clients

realm 管理员可以查看 realm 中的所有客户端。

manage-clients

realm 管理员可以查看manage realm 中的所有客户端和客户端作用域。

理解一些常见的用例

考虑这样一种情况:管理员想要允许一组管理员管理 realm 中的所有用户,但属于管理员组的用户除外。 此示例包括一个 test realm 和一个 test-admins 组。

允许管理员组管理用户

创建用户权限,允许 test-admins 组的成员查看和管理 realm 中的所有用户

  • 导航到管理控制台中的“权限”选项卡。

  • 单击“创建权限”,然后选择“用户”资源类型。

  • 填写名称,例如 禁止管理 test-admins

  • 选择 viewmanage 授权范围,保持选中“所有用户”。

  • 创建一个条件,需要满足该条件才能获得访问权限,方法是单击“创建新策略”。

  • 填写名称 允许 test-admins,选择“”作为“策略类型”。

  • 单击“添加组”按钮,选择 test-admins 组,单击“保存”。

  • 在“创建权限”页面上单击“保存”。

允许管理员组管理用户,但不包括组成员

让我们排除组成员本身,以便 test-admins 无法管理其他管理员。

  • 单击“创建权限”创建新权限。

  • 这次选择“”资源类型。

  • 填写名称,例如 禁止管理 test-admins

  • 选择 manage-members 授权范围。

  • 选择“特定组”,然后选择 test-admins 组。

  • 创建新策略,类型为“”。

  • 填写名称 禁止 test-admins,然后选择 test-admins 组。

  • 切换策略的“否定逻辑”,保存策略

  • 保存权限

允许具有特定角色的组成员模拟用户
  • 为您要允许模拟的特定用户(或所有用户)创建“用户权限”。

  • 创建“组策略”,允许访问 test-admins 的成员。

  • 创建“角色策略”,允许访问分配了 impersonation-admin 角色的用户。

  • 将这两个策略分配给权限。

将特定用户列入黑名单,禁止模拟
  • 为您要阻止模拟的特定用户创建“用户权限”。

  • 创建任何评估结果为拒绝的策略(例如,未选择用户的用户策略)。

  • 将策略分配给权限,以有效地阻止对所选用户进行模拟。

允许具有特定角色的管理员查看用户,但不管理用户
  • 为所有用户创建具有 view 范围的“用户权限”。

  • 创建“角色策略”,允许访问具有特定角色的用户。

  • 不要分配 manage 范围,以防止修改用户详细信息。

允许组成员管理用户和角色分配
  • 为所有用户创建具有 managemap-roles 范围的“用户权限”。

  • 创建“组策略”,允许访问 test-admins 的成员。

允许查看和管理组成员,但不包括其子组成员
  • 为特定组 mygroup 创建具有 view-membersmanage-members 范围的“组权限”。

  • 将目标为 test-admins 的“组策略”分配给它。

  • 为特定组创建另一个具有 view-membersmanage-members 范围的“组权限”,选择 mygroup 的所有子组。

  • test-admins 创建否定“组策略”,并将其分配给“子组”权限。

允许模拟特定组的成员
  • 为特定组 mygroup 创建具有 impersonate-members 的“组权限”。

  • 将目标为 mygroup-helpdesk 的“组策略”分配给它。

性能注意事项

在 realm 中启用此功能时,当 realm 管理员管理任何受支持的资源类型时,都会产生额外的开销。 当执行以下操作时,尤其如此

  • 列出和搜索

  • 更新或删除

每当您列出或管理 realm 资源时,该功能都会引入额外的检查,以便根据您定义的权限强制执行访问。 当查询 realm 资源时,尤其如此,因为部分评估 realm 管理员的权限以过滤和分页结果会产生额外的开销。

引用 realm 管理员用户及其可以访问的大多数资源的权限越少越好。 例如,如果您想委派对 realm 管理员的访问权限以管理用户,最好将这些用户作为组成员。 这样做不仅可以提高评估权限时的性能,还可以创建一个更易于管理的权限模型。

访问强制执行的主要影响是在查询 realm 资源时。 例如,如果 realm 管理员通过用户、角色或组策略在数千个权限中被引用,则在查询 realm 资源时发生的部分评估机制将从数据库中查询所有这些权限。 更简洁和优化的模型将有助于获取更少的权限,但足以授予或拒绝访问 realm 资源。

例如,使用组权限授予 realm 管理员查看和管理 realm 中用户的权限比为 realm 中的每个用户创建单独的权限更好。 并且确保与权限关联的策略(通过直接引用(用户策略)或间接引用(角色或组策略)引用 realm 管理员)不会跨越多个(数千个)权限,而与资源类型无关。

例如,假设您的 realm 中有三个用户,您想允许 realm 管理员 bob viewmanage 他们。 非最优的权限模型将为每个用户创建三个不同的权限,其中用户策略授予 bob 访问权限。 相反,您可以拥有单个组权限,甚至单个用户权限,将这三个用户分组,同时仍然使用相同的用户策略授予 bob 访问权限。

如果您想向更多 realm 管理员授予对这三个用户的访问权限,情况也是如此。 您可以考虑使用组策略或角色策略,而不是创建单独的策略。 权限模型是特定于用例的,但这些建议对于不仅提供更好的可管理性,而且还提高服务器在管理 realm 资源时的整体性能非常重要。

在服务器配置方面,根据 realm 的大小以及您拥有的权限和策略的数量,您可能需要考虑更改缓存配置以增加以下缓存的大小

  • 用户

  • 授权

考虑查看这些缓存的服务器指标,以找到调整部署大小的最佳值。

在过滤资源时,部分评估机制最终将依赖 SQL 语句中的 IN 子句来过滤结果。 根据您的数据库,您可能对 IN 子句的参数数量有限制。 Oracle 数据库的旧版本就是这种情况,它对参数数量有 1000 个的硬性限制。 为了避免此类问题,请记住上面关于授予或拒绝访问单个 realm 管理员的权限数量的注意事项。

细粒度管理员权限 V1

细粒度管理员权限 V1 已被新版本取代。 该功能的版本 1 仍标记为预览版并且可用,但将来可能会被弃用和删除。 要启用它,请使用 --features=admin-fine-grained-authz:v1 启动服务器。

有时,像 manage-realmmanage-users 这样的角色粒度太粗,您想要创建具有更细粒度权限的受限管理员帐户。 Keycloak 允许您为管理 realm 定义和分配受限访问策略。 诸如

  • 管理一个特定客户端

  • 管理属于特定组的用户

  • 管理组成员资格

  • 有限的用户管理。

  • 细粒度的模拟控制

  • 能够为用户分配一组特定的受限角色。

  • 能够为复合角色分配一组特定的受限角色。

  • 能够为客户端的作用域分配一组特定的受限角色。

  • 用于查看和管理用户、组、角色和客户端的新通用策略。

关于细粒度管理员权限,有一些重要事项需要注意

  • 细粒度管理员权限是在 授权服务之上实现的。 强烈建议您在深入了解细粒度权限之前,先阅读这些功能。

  • 细粒度权限仅在专用管理控制台和这些 realm 中定义的管理员中可用。 您无法定义跨 realm 的细粒度权限。

  • 细粒度权限用于授予额外的权限。 您无法覆盖内置管理员角色的默认行为。

管理一个特定的客户端

我们首先来看一下如何允许管理员仅管理一个客户端。在我们的示例中,我们有一个名为 test 的 realm 和一个名为 sales-application 的客户端。在 test realm 中,我们将授予该 realm 中的用户仅管理该应用程序的权限。

您无法进行跨 realm 的细粒度权限控制。master realm 中的管理员仅限于前面章节中定义的预定义管理员角色。
权限设置

我们首先要做的是登录到管理控制台,以便为该客户端设置权限。我们导航到要定义细粒度权限的客户端的管理部分。

客户端管理

Fine grain client

您应该看到一个名为 Permissions 的标签菜单项。点击该标签。

客户端权限标签

Fine grain client permissions tab

默认情况下,每个客户端都未启用细粒度权限。因此,请将 Permissions Enabled 开关切换到“开”以初始化权限。

如果您将 Permissions Enabled 开关切换到“关”,它将删除您为该客户端定义的所有权限。
客户端权限标签

Fine grain permission tab

当您将 Permissions Enabled 开关切换到“开”时,它会在后台使用 Authorization Services 初始化各种权限对象。对于本示例,我们对客户端的 manage 权限感兴趣。点击它会将您重定向到处理客户端 manage 权限的权限页面。所有授权对象都包含在 realm-management 客户端的 Authorization 标签中。

客户端管理权限

Fine grain client manage permission

首次初始化时,manage 权限没有任何关联的策略。您需要通过转到策略标签来创建一个。要快速到达那里,请点击上图所示的 Client details 链接。然后点击策略标签。

在此页面上,找到 Create client policy 按钮,您可以使用它来定义许多策略。您可以定义与角色或组关联的策略,甚至可以在 JavaScript 中定义规则。对于这个简单的示例,我们将创建一个 User Policy

用户策略

Fine grain client user policy

此策略将匹配用户数据库中的硬编码用户。在本例中,它是 sales-admin 用户。然后我们必须返回到 sales-application 客户端的 manage 权限页面,并将该策略分配给权限对象。

分配用户策略

Fine grain client assign user policy

sales-admin 用户现在有权管理 sales-application 客户端。

还有一件事我们必须做。转到 Users,选择 sales-admin 用户,然后转到 Role Mappings 标签,并将 query-clients 角色分配给该用户。

分配 query-clients

Fine grain assign query clients

为什么您必须这样做?此角色告诉管理控制台当 sales-admin 访问管理控制台时要呈现哪些菜单项。query-clients 角色告诉管理控制台,它应该为 sales-admin 用户呈现客户端菜单。

重要提示:如果您不设置 query-clients 角色,像 sales-admin 这样的受限管理员在登录到管理控制台时将看不到任何菜单选项。

测试一下

接下来,我们从 master realm 登出,然后使用 sales-admin 作为用户名重新登录到 test realm 的 专用管理控制台。它位于 /admin/test/console 下。

Sales admin 登录

Fine grain sales admin login

此管理员现在能够管理这一个客户端。

限制用户角色映射

您可能想要做的另一件事是限制管理员可以分配给用户的角色集。继续我们的上一个示例,让我们扩展 'sales-admin' 用户的权限集,以便他还可以控制哪些用户可以访问此应用程序。通过细粒度权限,我们可以启用它,以便 sales-admin 只能分配授予对 sales-application 特定访问权限的角色。我们还可以限制管理员只能映射角色,而不能执行任何其他类型的用户管理。

sales-application 定义了三个不同的客户端角色。

Sales application 角色

Fine grain sales application roles

我们希望 sales-admin 用户能够将这些角色映射到系统中的任何用户。执行此操作的第一步是允许管理员映射该角色。如果我们点击 viewLeads 角色,您将看到此角色有一个 Permissions 标签。

View leads 角色权限标签

Fine grain view leads role

如果我们点击该标签并将 Permissions Enabled 切换为“开”,您将看到我们可以将策略应用于许多操作。

View leads 权限

Fine grain view leads permissions

我们感兴趣的是 map-role。点击此权限并添加在前面示例中创建的相同用户策略。

映射角色权限

Fine grain map roles permission

我们所做的是声明 sales-admin 可以映射 viewLeads 角色。我们尚未做的是指定管理员允许将此角色映射到哪些用户。为此,我们必须转到此 realm 的管理控制台的 Users 部分。点击左侧菜单项 Users 会将我们带到 realm 的用户界面。您应该看到一个 Permissions 标签。点击它并启用它。

用户权限

Fine grain user permissions

我们感兴趣的权限是 map-roles。这是一个限制性策略,因为它仅允许管理员将角色映射到用户。如果我们点击 map-roles 权限并再次添加为此创建的用户策略,我们的 sales-admin 将能够将角色映射到任何用户。

我们要做的最后一件事是将 view-users 角色添加到 sales-admin。这将允许管理员查看他想要向其添加 sales-application 角色的 realm 中的用户。

添加 view-users

Fine grain add view users

测试一下

接下来,我们从 master realm 登出,然后使用 sales-admin 作为用户名重新登录到 test realm 的 专用管理控制台。它位于 /admin/test/console 下。

您将看到现在 sales-admin 可以查看系统中的用户。如果您选择其中一个用户,您将看到每个用户详细信息页面都是只读的,除了 Role Mappings 标签。转到此标签,您会发现除了浏览 sales-application 角色之外,管理员没有 Available 角色可以映射到用户。

分配 viewLeads

Fine grain add view leads

我们仅指定了 sales-admin 可以映射 viewLeads 角色。

每个客户端映射角色快捷方式

如果我们必须为 sales-application 发布的每个客户端角色都这样做,那将是乏味的。为了简化操作,有一种方法可以指定管理员可以映射由客户端定义的任何角色。如果我们登录回管理控制台到我们的 master realm 管理员,然后返回到 sales-application 权限页面,您将看到 map-roles 权限。

客户端映射角色权限

Fine grain client permissions

如果您授予管理员对此特定权限的访问权限,则该管理员将能够映射由客户端定义的任何角色。

完整的权限列表

除了管理特定客户端或客户端的特定角色之外,您还可以使用细粒度权限做更多的事情。本章定义了可以为 realm 描述的完整权限类型列表。

角色

当转到特定角色的 Permissions 标签时,您将看到列出的这些权限类型。

map-role

决定管理员是否可以将此角色映射到用户的策略。这些策略仅指定可以将角色映射到用户,而不是管理员被允许执行用户角色映射任务。管理员还必须具有管理或角色映射权限。有关更多信息,请参阅 用户权限

map-role-composite

决定管理员是否可以将此角色作为复合角色映射到另一个角色的策略。如果管理员必须管理客户端的权限,则可以为客户端定义角色,但他将无法向这些角色添加复合角色,除非他拥有要添加为复合角色的 map-role-composite 权限。

map-role-client-scope

决定管理员是否可以将此角色应用于客户端范围的策略。即使管理员可以管理客户端,除非授予此权限,否则他也没有权限为该客户端创建包含此角色的令牌。

客户端

当转到特定客户端的 Permissions 标签时,您将看到列出的这些权限类型。

view

决定管理员是否可以查看客户端配置的策略。

manage

决定管理员是否可以查看和管理客户端配置的策略。这里存在一些问题,即权限可能会被意外泄露。例如,即使管理员没有权限将角色映射到客户端范围,管理员也可以定义一个硬编码角色的协议映射器。这是当前协议映射器的局限性,因为它们没有像角色那样为它们分配单独权限的方法。

配置

用于管理客户端的减少的权限集。它类似于 manage 范围,但管理员不允许定义协议映射器、更改客户端模板或客户端范围。

map-roles

决定管理员是否可以将客户端定义的任何角色映射到用户的策略。这是一个快捷方式,易于使用的功能,避免了必须为客户端定义的每个角色定义策略。

map-roles-composite

决定管理员是否可以将客户端定义的任何角色作为复合角色映射到另一个角色的策略。这是一个快捷方式,易于使用的功能,避免了必须为客户端定义的每个角色定义策略。

map-roles-client-scope

决定管理员是否可以将客户端定义的任何角色映射到另一个客户端范围的策略。这是一个快捷方式,易于使用的功能,避免了必须为客户端定义的每个角色定义策略。

用户

当转到所有用户的 Permissions 标签时,您将看到列出的这些权限类型。

view

决定管理员是否可以查看 realm 中所有用户的策略。

manage

决定管理员是否可以管理 realm 中所有用户的策略。此权限授予管理员执行用户角色映射的权限,但它没有指定管理员允许映射哪些角色。您需要为您希望管理员能够映射的每个角色定义权限。

map-roles

这是 manage 范围授予的权限的子集。在本例中,管理员仅被允许映射角色。管理员不允许执行任何其他用户管理操作。此外,与 manage 一样,管理员允许应用的 roles 必须按角色或按角色集(如果处理客户端角色)指定。

manage-group-membership

类似于 map-roles,不同之处在于它与组成员身份有关:用户可以添加到哪些组或从哪些组中删除。这些策略仅授予管理员管理组成员身份的权限,而不是管理员允许管理哪些组的成员身份。您必须为每个组的 manage-members 权限指定策略。

impersonate

决定是否允许管理员模拟其他用户的策略。这些策略应用于管理员的属性和角色映射。

用户模拟

决定哪些用户可以被模拟的策略。这些策略将应用于被模拟的用户。例如,您可能想要定义一个策略,禁止任何人模拟具有管理员权限的用户。

当转到特定组的 Permissions 标签时,您将看到列出的这些权限类型。

view

决定管理员是否可以查看有关组信息的策略。

manage

决定管理员是否可以管理组配置的策略。

view-members

决定管理员是否可以查看组成员的用户详细信息的策略。

manage-members

决定管理员是否可以管理属于此组的用户的策略。

manage-membership

决定管理员是否可以更改组成员身份的策略。从组中添加或删除成员。

管理组织

当与客户或业务合作伙伴等第三方集成时,您可能希望将其身份与其他身份分开管理,并在他们与 realm 交互时,在整个业务生态系统中构建统一且安全的体验。

在 realm 中,组织代表这些第三方,以便 realm 或组织管理员可以按组织管理其成员的整个生命周期以及他们如何对 realm 进行身份验证和授权。

组织是开始使用 Keycloak 的 IAM 功能来解决企业对企业 (B2B) 用例的入口点。它在 realm 中启用多租户,以便用户可以访问 realm 中的受保护资源,但在更受限和受控的上下文中,该上下文是他们所属的组织。

Keycloak Organizations 是一项在 Keycloak 中启用组织支持的功能。目前,它提供了一些管理组织所需的核心功能,例如

  • 管理成员

  • 使用邀请链接加入组织成员

  • 通过身份代理联合其身份来加入组织成员

  • 在组织范围内进行身份验证时的身份优先登录和组织特定步骤

  • 通过令牌将组织特定的声明传播到应用程序以用于授权目的

在 Keycloak 中启用组织

要使用组织,您必须为当前 realm 启用此功能。

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 组织 切换为 开启

  3. 点击 保存

启用组织

Enabling Organizations

一旦启用该功能,您就可以通过菜单中可用的 组织 部分管理组织。

管理组织

组织 部分,您可以管理 realm 中的所有组织。

管理组织

Managing organizations

创建组织

步骤
  1. 点击 创建组织

创建组织

Creating organization

组织具有以下设置

名称

组织的易于理解的名称。该名称在 realm 内是唯一的。

别名

此组织的别名,用于在内部引用组织。别名在 realm 内是唯一的,并且必须是 URL 友好的,因此通常在 URL 中不允许的字符将不被允许在别名中使用。如果未设置,Keycloak 将尝试使用名称作为别名。如果名称不是 URL 友好的,您将收到错误,并且将被要求指定别名。一旦定义,别名之后就无法更改。

重定向 URL

在完成注册或接受通过电子邮件发送的组织邀请后,用户将自动重定向到指定的重定向 URL。如果留空,用户默认将被重定向到帐户控制台。

域名

属于此组织的一个或多个域名的集合。域名不能在 realm 内的不同组织之间共享。

描述

描述组织的自由文本字段。

创建组织后,您可以管理以下部分中描述的其他设置

理解组织域名

在管理组织时,与组织关联的域名在组织成员如何向 realm 验证身份以及如何验证其配置文件方面起着重要作用。

域名的一个关键作用是帮助识别用户所属的组织。通过查看用户的电子邮件地址,Keycloak 将使用相同的域名匹配相应的组织,并最终根据组织的要求更改身份验证流程。

域名还允许组织强制用户在其电子邮件中不允许使用与其组织关联的域名以外的域名。当用户及其身份从与组织关联的身份提供商联合而来,并且您想为他们的电子邮件地址强制使用特定的电子邮件域名时,此限制尤其有用。

禁用组织

要禁用组织,请将 已启用 切换为 关闭

禁用组织

Disabling organization

当组织被禁用时,您仍然可以通过管理界面管理它,但是组织成员无法向 realm 验证身份,包括通过与组织关联的身份提供商进行身份验证,因为它们也会自动被禁用。

但是,组织的非托管成员仍然能够向 realm 验证身份,因为他们也是 realm 用户,但是令牌将不包含有关他们与已禁用组织的关系的元数据。

有关托管和非托管用户的更多详细信息,请参阅 托管和非托管成员 部分。

删除组织

要删除组织,请在列表页面或编辑组织时,单击相应组织的 删除 操作。

删除组织

Deleting organization

删除组织时,将删除与其关联的所有数据,包括任何托管成员。

非托管用户和身份提供商保留在 realm 中,但它们不再链接到该组织。

有关托管和非托管用户的更多详细信息,请参阅 托管和非托管成员

管理属性

管理员可以使用属性存储有关组织的附加元数据。组织属性是一个键/值对,可以保存多个字符串值。

为此,请单击 属性 选项卡,并通过提供键和值来设置您想要的任何属性。

要为同一属性和键提供多个值,只需添加另一个具有相同键但值不同的属性即可。

管理组织属性

Managing organization attributes

管理成员

组织成员基本上是 realm 用户,但链接到单个组织。它们在逻辑上与 realm 中的其他用户分开,以便您确切地知道哪些用户属于组织。

有不同的方法可以将成员添加到组织或让成员加入组织

  • 添加现有域用户作为成员

  • 通过与组织关联的身份提供商

  • 发送邀请以创建新帐户

  • 发送邀请给现有用户以加入组织

一旦成为组织成员,就可以像管理 realm 中的任何常规帐户一样管理该用户的帐户,方法是访问菜单中的 用户 部分。

但是,您可以通过访问管理组织时的 成员 选项卡,将用户范围缩小到仅与组织关联的用户。在此选项卡中,您可以看到所有组织成员的列表,以及添加新成员以及编辑和删除现有成员的操作。

管理组织成员

Managing organization members

托管和非托管成员

在管理成员时,请考虑他们与组织的关系如何影响其帐户的生命周期。成员可以通过不同的流程加入组织,每个流程都表明其帐户与组织之间链接的强度。

有两种类型的成员

  • 托管

  • 非托管

托管成员是由组织管理的成员,他们不能在其组织之外存在。例如,考虑通过与组织关联的身份提供商创建的帐户。该帐户不属于 realm,因为它来自组织联合身份验证。在这种情况下,身份的单一来源是组织,其生命周期由组织控制。如果删除组织或成员,则该帐户也会从 realm 中删除。

另一方面,非托管成员是那些可以脱离组织而存在的成员。例如,当将现有 realm 用户添加到组织时,该帐户首先属于 realm,然后最终链接到组织。在这种情况下,删除组织或成员不会从 realm 中删除该帐户;realm 是身份的单一来源。

将现有 realm 用户添加为成员

现有 realm 用户可以通过从列表中选择该用户并将该用户添加到组织来加入组织。

步骤
  1. 点击 添加成员

  2. 点击 添加 realm 用户

  3. 选择一个或多个用户,然后点击 添加 以将他们添加到组织。

添加 realm 用户

Adding a realm user

一旦用户成为组织成员,该用户就可以像常规用户一样向 realm 验证身份,并使用 realm 支持的任何凭据。

邀请用户

管理员可以发送电子邮件邀请用户加入组织。

步骤
  1. 点击 添加成员

  2. 点击 邀请成员

  3. 提供电子邮件地址

  4. 点击 发送

邀请成员

Inviting members

可选地,您还可以为 名字姓氏 字段提供值,以便使用包含接收电子邮件的人的名字和姓氏的问候消息,使电子邮件消息更加个性化。

邀请基本上是发送一封电子邮件,其中包含一个链接,用户应单击该链接以执行加入组织所需的步骤。这些步骤取决于该人员是否已经在 realm 中拥有帐户,或者是否应在加入组织之前创建新帐户。

如果该电子邮件映射到 realm 中的现有用户,则用户将遵循的步骤基本上是确认加入组织的意图。

另一方面,如果没有用户与给定的电子邮件地址关联,则步骤将涉及通过 realm 的自助注册流程创建新帐户。在这种情况下,用户将被强制提供用于发送邀请的相同电子邮件地址。

使用身份提供商引导成员加入

组织可能拥有自己的身份提供商作为其身份的单一来源。在这种情况下,从身份提供商联合身份验证的用户将自动添加为组织成员。

当用户通过与组织关联的身份提供商加入组织时,他们会自动标记为托管成员。在这种情况下,他们将经历 realm 中配置的代理登录流程,并在成功验证身份后自动加入组织。

通过身份提供商引导新成员加入可以通过自动将用户重定向到组织的身份提供商或在登录页面选择身份提供商来完成。

在这两种情况下,一旦用户提供电子邮件,Keycloak 将尝试根据电子邮件域名匹配组织。如果电子邮件域名与组织匹配,并且身份提供商与同一域名关联,并且 当电子邮件域名匹配时重定向 设置已启用,则用户将自动重定向到身份提供商。一旦用户在身份提供商处验证身份并完成第一个代理登录流程,用户将自动添加为组织成员。

另一方面,如果 当电子邮件域名匹配时重定向 未启用,但身份提供商配置为不 在登录页面隐藏,则用户可以选择身份提供商,然后重定向到身份提供商以继续引导加入流程。

有关更多详细信息,请参阅 管理身份提供商

移除成员

您可以从组织中移除成员。

从您要移除的成员旁边的操作菜单中,单击 移除

从组织中移除成员时,请记住,用户是否会从 realm 中移除取决于该用户是托管成员还是非托管成员。

有关更多详细信息,请参阅 托管和非托管成员

对联合身份成员的支持

来自联合身份提供商的用户也可以添加为组织成员。唯一的例外是来自 导入模式禁用 的 LDAP 提供商的用户。组织成员被添加到未与外部提供商同步的内部组,因此即使 LDAP 提供商具有模式为 LDAP_ONLY 的组映射器,非导入用户也不可能添加为组织成员,因为该成员资格不会与 LDAP 服务器同步。

换句话说,未导入的 LDAP 用户无法加入组织,因为成员资格既未存储在本地数据库中,也未存储在 LDAP 服务器中。因此,如果您希望 LDAP 用户加入组织,请确保启用 LDAP 提供商的导入模式。

管理身份提供商

组织可能拥有自己的身份提供商作为其身份的单一来源。在这种情况下,您需要配置组织以使用组织的身份提供商验证用户身份,联合身份验证他们的身份,并最终将他们添加为组织成员。

组织可以关联一个或多个身份提供商,以便他们可以从不同的来源验证其用户,并对每个来源强制执行不同的约束。

在将身份提供商链接到组织之前,您需要从菜单中的身份提供商部分在 realm 级别创建一个组织。您可以将 realm 中可用的任何内置社交和身份提供商链接到组织。

将身份提供商链接到组织

可以从身份提供商选项卡将身份提供商链接到组织。如果身份提供商已存在,您将看到它们的列表以及搜索、编辑或从组织取消链接的选项。

组织身份提供商

Organization identity providers

步骤
  1. 单击链接身份提供商

  2. 选择一个身份提供商

  3. 设置适当的设置

  4. 点击 保存

链接身份提供商

Linking identity provider

身份提供商具有以下设置

身份提供商

您要链接到组织的身份提供商。一个身份提供商只能链接到一个组织。

域名

您要与身份提供商链接的组织域名。

在登录页面隐藏

如果当用户在组织范围内进行身份验证时,应在登录页面中隐藏此身份提供商。

当电子邮件域名匹配时重定向

当成员的电子邮件域名与为身份提供商设置的域名匹配时,是否应自动重定向到身份提供商。如果域名设置为 Any,则电子邮件域名与任何组织域名匹配的成员将被重定向到身份提供商。

如果组织链接了多个身份提供商,则组织验证器会优先选择与用户电子邮件域名匹配的提供商进行自动重定向。如果找不到,它会尝试查找域名设置为 Any 的提供商。

一旦链接到组织,就可以像在 realm 中管理任何其他提供商一样管理身份提供商,只需访问菜单中的身份提供商部分即可。但是,本文描述的选项仅在组织范围内管理身份提供商时可用。唯一的例外是为方便起见在此处提供的在登录页面隐藏选项。

编辑链接的身份提供商

您可以随时编辑链接的身份提供商的任何组织相关设置。

步骤
  1. 在菜单中,单击组织,然后转到身份提供商选项卡。

  2. 在列表中找到身份提供商

    您可以为此步骤使用搜索选项。

  3. 单击行尾的操作按钮(三个点)。

  4. 单击编辑

  5. 进行必要的更改。

  6. 点击 保存

编辑链接的身份提供商

Editing linked identity provider

从组织取消链接身份提供商

当从组织取消链接身份提供商时,它仍然作为 realm 级别的提供商可用,但不再与组织关联。要删除取消链接的提供商,请使用菜单中的身份提供商部分。

步骤
  1. 在菜单中,单击组织,然后转到身份提供商选项卡。

  2. 在列表中找到身份提供商

    您可以为此步骤使用搜索功能。

  3. 单击行尾的操作按钮(三个点)。

  4. 单击取消链接提供商

取消链接身份提供商

Unlinking identity provider

验证成员身份

当您为 realm 启用组织时,用户身份验证会发生更改。如果用户被识别为在组织的上下文中进行身份验证,则身份验证流程会根据每个组织而变化。

创建 realm 时,身份验证流程会自动更新,以启用特定步骤来验证组织成员身份和引导组织成员。更新的身份验证流程包括

  • 浏览器

  • 首次代理登录

浏览器流程的主要更改是,它默认使用身份优先登录,以便在提示用户输入凭据之前识别用户。关于首次代理登录流程,主要更改是在用户通过与组织关联的身份提供商进行身份验证并成功完成流程后,自动将用户添加为组织成员。

是否选择使用身份优先登录取决于 realm 中是否存在组织。如果不存在组织,用户将按照通常的步骤,使用用户名和密码或在浏览器流程中配置的任何其他步骤进行身份验证。否则,系统会首先要求用户提供用户名或电子邮件,以便继续对 realm 进行身份验证。

身份优先登录的主要目标是识别用户

  • 用户是现有用户还是新用户?

  • 用户是否是 realm 内任何组织的成员?

  • 如果是组织成员,用户是否链接到与组织关联的任何身份提供商?

根据识别用户的结果,身份验证流程会更改为继续进行身份验证(要求用户提供凭据),或者最终自动重定向用户,以便通过身份提供商在组织安全边界内进行身份验证。

了解身份优先登录

除了在提供用户名后识别用户之外,身份优先登录还负责

  • 将电子邮件域名与组织匹配。

  • 如果提供的用户名已存在帐户,则决定是否应继续身份验证流程

  • 根据域名和身份提供商如何配置到组织,决定用户应如何进行身份验证

  • 如果电子邮件域名与为身份提供商设置的域名匹配,则通过与组织关联的身份提供商无缝验证用户身份

身份优先登录提供与通常的登录页面(带有用户名和密码字段)相同的功能。用户仍然可以通过单击注册链接进行自助注册,或者选择未链接到该 realm 中组织的任何身份或社交代理。

身份优先登录页面

Identity-first login page

如果用户不存在,并且该用户尝试使用与组织域名匹配的电子邮件域名进行身份验证,则身份优先登录页面将再次出现,并显示一条消息,指出提供的用户名无效。此时,无需再要求用户提供凭据。

用户不存在时的身份优先

Identity-first login error

有几种选项可用于注册用户,允许该用户验证 realm 身份并加入组织。

如果 realm 启用了自助注册设置,则用户可以单击身份优先登录页面上的注册链接,并在 realm 创建一个帐户。之后,管理员可以向用户发送邀请链接,或者手动将用户添加为组织成员。有关更多详细信息,请参阅管理成员

如果组织具有没有域名的身份提供商,并且在登录页面隐藏设置为关闭,则用户还可以单击身份优先登录页面上的身份提供商链接,以自动创建一个帐户并在通过身份提供商进行身份验证后加入组织。有关更多详细信息,请参阅管理身份提供商

在与上一节类似的情况下,组织可能已设置了具有组织域名之一的身份提供商。在这种情况下,如果用户的电子邮件与组织的特定域名匹配,则用户将被重定向到身份提供商。流程完成后,将创建一个帐户,并且用户加入组织。

配置现有身份验证流程

如前所述,对于新的 realm,身份验证流程会自动更新必要的步骤,以支持组织并验证其成员身份。对于现有 realm,除了为 realm 启用组织之外,您还需要手动更新现有的(自定义)身份验证流程。

通过以下步骤更改 browser 流程

步骤
  1. 复制绑定到 Browser flow 绑定类型的当前流程,以避免破坏您当前正在使用的流程

  2. 单击添加子流程并为其命名,例如 我的组织

  3. 将新添加的 我的组织 子流程移动到紧接在 身份提供商重定向器 执行步骤之后执行。这里的重点是,子流程应在任何其他子流程或执行步骤之前发生,这些子流程或执行步骤使用您在 realm 中支持的任何凭据来验证用户身份。添加后,将 要求 更改为 备选

  4. 我的组织 子流程中单击添加子流程,并为其命名,例如 我的组织 - 条件式。添加后,将 要求 更改为 条件式

  5. 我的组织 - 条件式 子流程中单击添加条件,然后选择 条件 - 用户已配置。添加后,将 要求 更改为 必需

  6. 我的组织 - 条件式 子流程中单击添加步骤,然后选择 *组织身份优先登录

    • 执行步骤。添加后,将 要求 更改为 备选

  7. 将身份验证流程绑定到 Browser 绑定类型。

组织浏览器流程

Organizations browser flow

一旦您为 realm 启用组织设置并至少创建一个组织,您应该能够看到身份优先登录页面并开始在 realm 中使用组织。

通过以下步骤更改 first broker login 流程

步骤
  1. 复制绑定到 First broker login flow 绑定类型的当前流程,以避免破坏您当前正在使用的流程

  2. 单击添加子流程并为其命名,例如 组织成员 - 条件式。添加后,将 要求 更改为 条件式

  3. 组织成员 - 条件式 子流程中单击添加条件,然后选择 条件 - 用户已配置。添加后,将 要求 更改为 必需

  4. 组织成员 - 条件式 子流程中单击添加步骤,然后选择 组织成员入职 执行步骤。添加后,将 要求 更改为 必需

  5. 将身份验证流程绑定到 First broker login 绑定类型。

组织首次代理流程

Organizations first broker flow

现在,您应该能够使用与组织关联的任何身份提供商进行身份验证,并在用户完成首次浏览器登录流程后立即加入组织成为成员。

配置用户身份验证方式

如果流程支持组织,您可以配置某些步骤来更改用户对 realm 进行身份验证的方式。

例如,某些用例将要求用户仅当他们是 realm 中任何组织或特定组织的成员时才对 realm 进行身份验证。

要启用此行为,您需要在 组织身份优先登录 执行步骤上启用 需要用户成员资格 设置,方法是单击其设置。

如果启用,并且在用户在身份优先登录页面中提供用户名或电子邮件后,服务器将尝试解析用户是其成员的组织,方法是查找任何现有成员资格或基于客户端请求的 组织 范围的语义。如果不是组织成员,则会显示错误页面。

映射组织声明

要将组织特定的声明映射到令牌中,客户端需要在向服务器发送授权请求时请求 organization 范围。当在组织的上下文中进行身份验证时,客户端可以请求 organization 范围来映射有关用户是其成员的组织的信息。

因此,令牌将包含如下声明

"organization": {
  "testcorp": {
    "id": "42c3e46f-2477-44d7-a85b-d3b43f6b31fa",
    "attr1": [
      "value1"
    ]
  }
}

客户端(例如,来自 ID 令牌)和资源服务器(例如,来自访问令牌)可以使用组织声明来授权访问受保护的资源,具体取决于用户是其成员的组织。

organization 范围是 realm 中内置的可选客户端范围。因此,默认情况下,此范围会添加到 realm 中创建的任何客户端。它还定义了 Organization Membership 映射器,该映射器控制组织成员资格信息如何映射到令牌。

默认情况下,组织 ID 和属性不包含在组织声明中。要包含它们,请编辑映射器并分别启用添加组织 ID添加组织属性选项。
在组织声明中包含属性

Including attributes in the organization claim

organization 范围使用不同的格式请求

格式 描述

组织

如果用户仅属于一个组织,则映射到该组织。否则,如果用户属于多个组织,则在用户向 realm 进行身份验证时,将提示用户选择一个组织。

组织:<别名>

映射到具有给定别名的单个组织。

组织:*

映射到用户所属的所有组织。

管理 OpenID Connect 和 SAML 客户端

客户端是可以请求用户身份验证的实体。客户端有两种形式。第一种客户端是想要参与单点登录的应用程序。这些客户端只是希望 Keycloak 为它们提供安全性。另一种客户端是请求访问令牌的客户端,以便它可以代表经过身份验证的用户调用其他服务。本节讨论配置客户端的各个方面以及执行此操作的各种方法。

管理 OpenID Connect 客户端

OpenID Connect 是推荐的用于保护应用程序的协议。它从一开始就被设计为对 Web 友好,并且最适合 HTML5/JavaScript 应用程序。

创建 OpenID Connect 客户端

要保护使用 OpenID Connect 协议的应用程序,您需要创建一个客户端。

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 点击 创建客户端

    创建客户端

    Create Client

  3. 客户端类型 设置为 OpenID Connect

  4. 输入 客户端 ID

    此 ID 是一个字母数字字符串,用于 OIDC 请求和 Keycloak 数据库中以标识客户端。

  5. 为客户端提供 名称

    如果您计划本地化此名称,请设置一个替换字符串值。例如,字符串值可以是 ${myapp}。有关更多信息,请参阅《服务器开发者指南》

  6. 点击 保存

此操作将创建客户端,并将您带到 设置 选项卡,您可以在其中执行基本配置

基本配置

设置 选项卡包含许多用于配置此客户端的选项。

设置选项卡

Settings tab

常规设置
客户端 ID

用于 OIDC 请求和 Keycloak 数据库中标识客户端的字母数字 ID 字符串。

名称

Keycloak UI 界面中客户端的名称。要本地化名称,请设置一个替换字符串值。例如,字符串值可以是 ${myapp}。有关更多信息,请参阅《服务器开发者指南》

描述

客户端的描述。此设置也可以本地化。

始终在控制台中显示

即使此用户没有活动会话,也始终在帐户控制台中列出此客户端。

访问设置
根 URL

如果 Keycloak 使用任何配置的相对 URL,则此值将添加到它们的前面。

主页 URL

当身份验证服务器需要重定向或链接回客户端时,提供默认 URL。

有效重定向 URI

必填字段。输入 URL 模式,然后单击 + 添加,单击 - 删除现有 URL,然后单击 保存。精确(区分大小写)字符串匹配用于比较有效的重定向 URI。

您可以在 URL 模式的末尾使用通配符。例如 http://host.com/path/*。为了避免安全问题,如果传递的重定向 URI 包含 userinfo 部分,或者其路径管理对父目录 (/../) 的访问,则不执行通配符比较,而是执行标准且安全的精确字符串匹配。

完整的通配符 * 有效重定向 URI 也可以配置为允许任何 http 或 https 重定向 URI。请不要在生产环境中使用它。

独占重定向 URI 模式通常更安全。有关更多信息,请参阅非特定重定向 URI

Web 源

输入 URL 模式,然后单击 + 添加,单击 - 删除现有 URL。单击 保存

此选项处理跨域资源共享 (CORS)。如果浏览器 JavaScript 尝试向域与 JavaScript 代码来源域不同的服务器发出 AJAX HTTP 请求,则该请求必须使用 CORS。服务器必须处理 CORS 请求,否则浏览器将不会显示或允许处理该请求。此协议可防止 XSS、CSRF 和其他基于 JavaScript 的攻击。

此处列出的域 URL 嵌入在发送到客户端应用程序的访问令牌中。客户端应用程序使用此信息来决定是否允许在其上调用 CORS 请求。只有 Keycloak 客户端适配器支持此功能。有关更多信息,请参阅《保护应用程序指南》

管理 URL

客户端的回调端点。服务器使用此 URL 进行回调,例如推送吊销策略、执行后端注销和其他管理操作。对于 Keycloak servlet 适配器,此 URL 可以是 servlet 应用程序的根 URL。有关更多信息,请参阅《保护应用程序指南》

功能配置
客户端身份验证

OIDC 客户端的类型。

  • 开启

    对于执行浏览器登录并在发出访问令牌请求时需要客户端密钥的服务器端客户端。此设置应用于服务器端应用程序。

  • 关闭

    对于执行浏览器登录的客户端客户端。由于无法确保客户端客户端的密钥安全,因此通过配置正确的重定向 URI 来限制访问非常重要。

Authorization

启用或禁用对此客户端的细粒度授权支持。

标准流程

如果启用,此客户端可以使用 OIDC 授权码流程

直接访问授权

如果启用,此客户端可以使用 OIDC 直接访问授权

隐式流程

如果启用,此客户端可以使用 OIDC 隐式流程

服务帐户角色

如果启用,此客户端可以向 Keycloak 进行身份验证并检索专用于此客户端的访问令牌。根据 OAuth2 规范,这为此客户端启用了对 客户端凭据授权 的支持。

标准令牌交换

如果启用,此客户端可以使用标准令牌交换

Auth 2.0 设备授权许可

如果启用,此客户端可以使用 OIDC 设备授权许可

OIDC CIBA 许可

如果启用,此客户端可以使用 OIDC 客户端发起的后端通道身份验证许可

登录设置
登录主题

用于登录、OTP、授权注册和忘记密码页面的主题。

需要同意

如果启用,用户必须同意客户端访问。

对于执行浏览器登录的客户端客户端。由于无法确保客户端客户端的密钥安全,因此通过配置正确的重定向 URI 来限制访问非常重要。

在屏幕上显示客户端

此开关在 需要同意关闭 时适用。

  • 关闭

    同意屏幕将仅包含与配置的客户端作用域相对应的同意项。

  • 开启

    同意屏幕上还将有一个关于此客户端本身的条目。

客户端同意屏幕文本

需要同意在屏幕上显示客户端 都启用时适用。包含同意屏幕上关于此客户端权限的文本。

注销设置
前端通道注销

如果启用 前端通道注销,则应用程序应能够按照 OpenID Connect 前端通道注销 规范通过前端通道注销用户。如果启用,您还应该提供 前端通道注销 URL

前端通道注销 URL

Keycloak 将使用此 URL 通过前端通道向客户端发送注销请求。如果未提供,则默认为 “主页 URL”。此选项仅在 前端通道注销 选项为 “开启” 时适用。

前端通道注销会话要求

指定在使用 前端通道注销 URL 时,注销请求中是否包含 sid(会话 ID)和 iss(颁发者)参数。

后端通道注销 URL

当向此 realm 发送注销请求(通过 end_session_endpoint)时,此 URL 将导致客户端自行注销。注销是通过发送 OIDC 后端通道注销规范中指定的注销令牌来完成的。如果省略,注销请求可能会以 Keycloak 适配器特定的格式发送到指定的 管理 URL(如果已配置)。如果甚至 管理 URL 都未配置,则不会向客户端发送注销请求。此选项仅在 前端通道注销 选项为 “关闭” 时适用。

后端通道注销会话要求

指定在使用 后端通道注销 URL 时,会话 ID 声明是否包含在注销令牌中。

后端通道注销撤销离线会话

指定在使用 “后端通道注销 URL” 时,revoke_offline_access 事件是否包含在注销令牌中。当 Keycloak 收到包含此事件的注销令牌时,将撤销离线会话。

高级配置

完成 设置 选项卡上的字段后,您可以使用其他选项卡执行高级配置。例如,您可以使用 角色客户端作用域 选项卡来配置为客户端定义的客户端角色或管理客户端的客户端作用域。此外,有关其他功能,请参阅本章的其余部分。

高级选项卡

当您单击 高级 选项卡时,将显示其他字段。有关特定字段的详细信息,请单击该字段的问号图标。但是,本节详细描述了某些字段。

细粒度 OpenID Connect 配置

Logo URL

引用客户端应用程序 Logo 的 URL。

策略 URL

依赖方客户端向最终用户提供的 URL,用于阅读有关如何使用个人资料数据的说明。

服务条款 URL

依赖方客户端向最终用户提供的 URL,用于阅读有关依赖方服务条款的说明。

签名和加密 ID 令牌支持

Keycloak 可以根据 Json Web Encryption (JWE) 规范加密 ID 令牌。管理员确定是否为每个客户端加密 ID 令牌。

用于加密 ID 令牌的密钥是内容加密密钥 (CEK)。Keycloak 和客户端必须协商使用哪个 CEK 以及如何传递它。用于确定 CEK 的方法是密钥管理模式。“密钥加密” 是 Keycloak 支持的密钥管理模式。

在密钥加密中

  1. 客户端生成非对称加密密钥对。

  2. 公钥用于加密 CEK。

  3. Keycloak 为每个 ID 令牌生成一个 CEK

  4. Keycloak 使用生成的 CEK 加密 ID 令牌

  5. Keycloak 使用客户端的公钥加密 CEK。

  6. 客户端使用其私钥解密加密的 CEK

  7. 客户端使用解密的 CEK 解密 ID 令牌。

除了客户端之外,任何一方都无法解密 ID 令牌。

客户端必须将其用于加密 CEK 的公钥传递给 Keycloak。Keycloak 支持从客户端提供的 URL 下载公钥。客户端必须根据 Json Web Keys (JWK) 规范提供公钥。

步骤如下

  1. 打开客户端的 密钥 选项卡。

  2. JWKS URL 切换为 “开启”。

  3. JWKS URL 文本框中输入客户端的公钥 URL。

密钥加密的算法在 Json Web Algorithm (JWA) 规范中定义。Keycloak 支持

  • RSAES-PKCS1-v1_5(RSA1_5)

  • 使用默认参数的 RSAES OAEP (RSA-OAEP)

  • 使用 SHA-256 和 MFG1 的 RSAES OAEP 256 (RSA-OAEP-256)

选择算法的步骤如下

  1. 打开客户端的 高级 选项卡。

  2. 打开 细粒度 OpenID Connect 配置

  3. ID 令牌加密内容加密算法 下拉菜单中选择算法。

OpenID Connect 兼容模式

本节是为了向后兼容而存在的。单击问号图标以获取每个字段的详细信息。

启用 OAuth 2.0 相互 TLS 证书绑定访问令牌

相互 TLS 将访问令牌和刷新令牌与客户端证书绑定在一起,该证书在 TLS 握手期间交换。这种绑定可以防止攻击者使用被盗的令牌。

这种类型的令牌是持有者密钥令牌。与持有者令牌不同,持有者密钥令牌的接收者可以验证令牌的发送者是否合法。

如果此设置开启,则工作流程如下

  1. 令牌请求在授权码流程或混合流程中发送到令牌端点。

  2. Keycloak 请求客户端证书。

  3. Keycloak 接收客户端证书。

  4. Keycloak 成功验证客户端证书。

如果验证失败,Keycloak 将拒绝令牌。

在以下情况下,Keycloak 将验证发送访问令牌或刷新令牌的客户端

  • 令牌刷新请求与持有者密钥刷新令牌一起发送到令牌端点。

  • UserInfo 请求与持有者密钥访问令牌一起发送到 UserInfo 端点。

  • 注销请求与持有者密钥刷新令牌一起发送到不符合 OIDC 标准的 Keycloak 专有注销端点。

有关更多详细信息,请参阅 OAuth 2.0 相互 TLS 客户端身份验证和证书绑定访问令牌中的相互 TLS 客户端证书绑定访问令牌

Keycloak 客户端适配器不支持持有者密钥令牌验证。Keycloak 适配器将访问令牌和刷新令牌视为持有者令牌。

OAuth 2.0 在应用层证明所有权 (DPoP)

DPoP 将访问令牌和刷新令牌与客户端密钥对的公钥部分绑定在一起。这种绑定可以防止攻击者使用被盗的令牌。

这种类型的令牌是持有者密钥令牌。与持有者令牌不同,持有者密钥令牌的接收者可以验证令牌的发送者是否合法。

如果客户端开关 在令牌请求中需要证明所有权 (DPoP) 标头 开启,则工作流程如下

  1. 令牌请求在授权码流程或混合流程中发送到令牌端点。

  2. Keycloak 请求 DPoP 证明。

  3. Keycloak 接收 DPoP 证明。

  4. Keycloak 成功验证 DPoP 证明。

如果验证失败,Keycloak 将拒绝令牌。

如果开关 在令牌请求中需要证明所有权 (DPoP) 标头 关闭,客户端仍然可以在令牌请求中发送 DPoP 证明。在这种情况下,Keycloak 将验证 DPoP 证明并将指纹添加到令牌。但是,如果开关关闭,则 Keycloak 服务器不会为此客户端强制执行 DPoP 绑定。如果您想确保特定客户端始终使用 DPoP 绑定,建议开启此开关。

在以下情况下,Keycloak 将验证发送访问令牌或刷新令牌的客户端

  • 令牌刷新请求与持有者密钥刷新令牌一起发送到令牌端点。此验证仅针对 DPoP 规范中描述的公共客户端完成。对于机密客户端,由于已通过适当的客户端凭据进行客户端身份验证以确保请求来自合法客户端,因此不进行验证。对于公共客户端,访问令牌和刷新令牌都绑定了 DPoP。对于机密客户端,只有访问令牌绑定了 DPoP。

  • UserInfo 请求与持有者密钥访问令牌一起发送到 UserInfo 端点。

  • 注销请求与持有者密钥刷新令牌一起发送到不符合 OIDC 标准的 Keycloak 专有注销端点。此验证仅针对上述公共客户端完成。

有关更多详细信息,请参阅 OAuth 2.0 证明所有权 (DPoP)

Keycloak 客户端适配器不支持 DPoP 持有者密钥令牌验证。Keycloak 适配器将访问令牌和刷新令牌视为持有者令牌。

DPoP 是预览功能,尚未完全支持。此功能默认禁用。

要启用,请使用 --features=preview--features=dpop 启动服务器

OIDC 的高级设置

OpenID Connect 的高级设置允许您在客户端级别为会话和令牌超时配置覆盖。

Advanced Settings

配置 描述

访问令牌生命周期

该值会覆盖同名的 realm 选项。

客户端会话空闲

该值会覆盖同名的 realm 选项。该值应短于全局的 SSO 会话空闲

客户端会话最大值

该值会覆盖同名的 realm 选项。该值应短于全局的 SSO 会话最大

客户端离线会话空闲

此设置允许您为客户端配置更短的离线会话空闲超时。超时是指会话保持空闲的时间量,超过此时间后,Keycloak 将撤销其离线令牌。如果未设置,则使用 realm 的 离线会话空闲

客户端离线会话最大

此设置允许您为客户端配置更短的离线会话最大生命周期。生命周期是指 Keycloak 撤销相应离线令牌之前的最长时间。此选项需要全局在 realm 中启用离线会话最大受限,并且默认为离线会话最大

代码交换的代码质询方法证明密钥

如果攻击者窃取了合法客户端的授权码,代码交换的密钥证明 (PKCE) 可防止攻击者接收应用于该代码的令牌。

管理员可以选择以下选项之一

(空白)

除非客户端向 Keycloak 授权端点发送适当的 PKCE 参数,否则 Keycloak 不会应用 PKCE。

S256

Keycloak 应用于代码质询方法为 S256 的客户端 PKCE。

plain

Keycloak 应用于代码质询方法为 plain 的客户端 PKCE。

有关更多详细信息,请参阅 RFC 7636 OAuth 公共客户端的代码交换的密钥证明

ACR 到身份验证级别 (LoA) 映射

在客户端的高级设置中,您可以定义哪个 身份验证上下文类引用 (ACR) 值映射到哪个 身份验证级别 (LoA)。此映射也可以在 realm 中指定,如ACR 到 LoA 映射中所述。最佳实践是在 realm 级别配置此映射,这允许跨多个客户端共享相同的设置。

当从该客户端向 Keycloak 发送登录请求时,如果没有 acr_values 参数,也没有附加 acr 声明的 claims 参数,则可以使用 默认 ACR 值 来指定默认值。请参阅 官方 OIDC 动态客户端注册规范

请注意,默认 ACR 值用作默认级别,但是,它不能可靠地用于强制使用特定级别登录。例如,假设您将 默认 ACR 值 配置为级别 2。然后,默认情况下,将要求用户使用级别 2 进行身份验证。但是,当用户显式地将参数附加到登录请求中,例如 acr_values=1 时,将使用级别 1。因此,如果客户端确实需要级别 2,则建议客户端检查 ID 令牌中是否存在 acr 声明,并仔细检查它是否包含请求的级别 2。要在 Keycloak 端实际强制使用某个 ACR,请使用 最小 ACR 值 设置。这允许管理员即使在无法验证令牌中请求的 acr 声明的应用程序上,也能强制执行 ACR。

ACR to LoA mapping

有关更多详细信息,请参阅 逐步验证官方 OIDC 规范

机密客户端凭据

如果客户端的客户端身份验证设置为 开启,则必须在 凭据 选项卡下配置客户端的凭据。

凭据选项卡

Credentials Tab

客户端身份验证器下拉列表指定要用于客户端的凭据类型。

客户端 ID 和密钥

此选项是默认设置。密钥会自动生成。如有必要,单击 重新生成 以重新创建密钥。

签名 JWT

Signed JWT

签名 JWT 是“签名 JSON Web 令牌”。

在此身份验证器中,您可以强制执行客户端使用的 签名算法(默认情况下任何算法都有效)以及 JWT 令牌允许的 最大过期时间(在此期间之后收到的令牌将不被接受,因为它们太旧了,请注意令牌应在身份验证之前立即颁发,默认为 60 秒)。

选择此凭据类型时,您还必须在 密钥 选项卡中为客户端生成私钥和证书。私钥将用于签署 JWT,而证书将由服务器用于验证签名。

密钥选项卡

Keys tab

单击 生成新密钥 按钮开始此过程。

生成密钥

generate client keys

  1. 选择要使用的存档格式。

  2. 输入 密钥密码

  3. 输入 存储密码

  4. 单击 生成

当您生成密钥时,Keycloak 将存储证书,您可以下载客户端的私钥和证书。

您还可以使用外部工具生成密钥,然后通过单击 导入证书 来导入客户端的证书。

导入证书

Import Certificate

  1. 选择证书的存档格式。

  2. 输入存储密码。

  3. 单击 导入文件 选择证书文件。

  4. 单击 导入

如果您单击 使用 JWKS URL,则无需导入证书。在这种情况下,您可以提供在 JWK 格式中发布公钥的 URL。使用此选项,如果密钥发生更改,Keycloak 会重新导入密钥。

如果您正在使用由 Keycloak 适配器保护的客户端,您可以使用此格式配置 JWKS URL,假设 https://myhost.com/myapp 是您的客户端应用程序的根 URL

https://myhost.com/myapp/k_jwks

有关更多详细信息,请参阅 服务器开发人员指南

使用客户端密钥签名的 JWT

如果选择此选项,您可以使用客户端密钥而不是私钥签名的 JWT。

客户端密钥将由客户端用于签署 JWT。

签名 JWT 身份验证器一样,您可以配置 签名算法 和 JWT 令牌的 最大过期时间

X509 证书

Keycloak 将验证客户端在 TLS 握手期间是否使用了正确的 X509 证书。

X509 证书

x509 client auth

验证器还会使用配置的正则表达式验证表达式检查证书的 Subject DN 字段。对于某些用例,接受所有证书就足够了。在这种情况下,您可以使用 (.*?)(?:$) 表达式。

Keycloak 有两种方法可以从请求中获取客户端 ID

  • 查询中的 client_id 参数(在 OAuth 2.0 规范的第 2.2 节中描述)。

  • 以表单参数形式提供 client_id

客户端密钥轮换

请注意,客户端密钥轮换支持正在开发中。实验性地使用此功能。

对于具有机密 客户端身份验证的客户端,Keycloak 支持通过客户端策略轮换客户端密钥的功能。

客户端密钥轮换策略提供更高的安全性,以减轻诸如密钥泄露等问题。启用后,Keycloak 最多支持每个客户端同时拥有两个活动密钥。该策略根据以下设置管理轮换

  • 密钥过期时间: [秒] - 轮换密钥时,这是新密钥的过期时间。添加到密钥创建日期的时长,以秒为单位。在策略执行时计算。

  • 已轮换密钥过期时间: [秒] - 轮换密钥时,此值是旧密钥的剩余过期时间。此值应始终小于密钥过期时间。当值为 0 时,旧密钥将在客户端轮换期间立即删除。添加到密钥轮换日期的时长,以秒为单位。在策略执行时计算。

  • 更新期间轮换的剩余过期时间: [秒] - 动态客户端更新应执行客户端密钥轮换的时间段。在策略执行时计算。

当发生客户端密钥轮换时,将生成一个新的主密钥,旧的客户端主密钥将变为辅助密钥,并具有新的过期日期。

客户端密钥轮换规则

轮换不会自动发生或通过后台进程发生。为了执行轮换,需要在客户端上执行更新操作,可以通过 Keycloak 管理控制台通过客户端凭据选项卡中的 重新生成密钥 功能或 Admin REST API 来完成。当调用客户端更新操作时,会根据以下规则发生密钥轮换

  • 密钥过期时间 的值小于当前日期时。

  • 在动态客户端注册客户端更新请求期间,如果 更新期间轮换的剩余过期时间 的值与当前日期和 密钥过期时间 之间的时间段匹配,则客户端密钥将自动轮换。

此外,可以通过 Admin REST API 随时强制执行客户端密钥轮换。

在创建新客户端期间,如果客户端密钥轮换策略处于活动状态,则将自动应用该行为。

要将密钥轮换行为应用于现有客户端,请在定义策略后更新该客户端,以便应用该行为。

创建 OIDC 客户端密钥轮换策略

以下是定义密钥轮换策略的示例

步骤
  1. 在菜单中单击“Realm 设置”。

  2. 单击 客户端策略 选项卡。

  3. 配置文件 页面上,单击 创建客户端配置文件

    创建配置文件

    Create Client Profile

  4. 名称 中输入任何名称。

  5. 描述 中输入描述,以帮助您识别配置文件的用途。

  6. 点击 保存

    此操作将创建配置文件,并允许您配置执行器。

  7. 单击 添加执行器 以为此配置文件配置执行器。

    创建配置文件执行器

    Client Profile Executor

  8. 执行器类型 选择 secret-rotation

  9. 密钥过期时间 输入每个密钥的最大持续时间,以秒为单位。

  10. 已轮换密钥过期时间 输入每个已轮换密钥的最大持续时间,以秒为单位。

    请记住,已轮换密钥过期时间 值必须始终小于 密钥过期时间
  11. 剩余过期时间 输入时间量(以秒为单位),在此时间之后,任何更新操作都将更新客户端。

  12. 点击 添加

    在上面的示例中

    • 每个密钥有效期为一周。

    • 轮换后的密钥在两天后过期。

    • 动态客户端的更新窗口在密钥过期前一天开始。

  13. 返回到 客户端策略 选项卡。

  14. 单击 策略

  15. 单击 创建客户端策略

    创建客户端密钥轮换策略

    Client Rotation Policy

  16. 名称 中输入任何名称。

  17. 描述中输入描述,以帮助您识别策略的用途。

  18. 点击 保存

    此操作将创建策略,并使您可以将策略与配置文件关联。它还允许您配置策略执行的条件。

  19. 在“条件”下,单击添加条件

    创建客户端密钥轮换策略条件

    Client Rotation Policy Condition

  20. 要将行为应用于所有机密客户端,请在“条件类型”字段中选择client-access-type

    要应用于特定客户端组,另一种方法是在“条件类型”字段中选择client-roles类型。 这样,您可以创建特定的角色,并为每个角色分配自定义轮换配置。

  21. 在“客户端访问类型”字段中添加confidential

  22. 点击 添加

  23. 返回策略设置中的“客户端配置文件”下,单击添加客户端配置文件,然后从列表中选择“每周客户端密钥轮换配置文件”,然后单击添加

    客户端密钥轮换策略

    Client Rotation Policy

要将密钥轮换行为应用于现有客户端,请按照以下步骤操作

使用管理控制台
  1. 单击菜单中的 Clients(客户端)。

  2. 单击客户端。

  3. 单击 凭据 选项卡。

  4. 单击客户端密钥的重新生成


使用客户端 REST 服务,可以通过两种方式执行
  • 通过客户端上的更新操作

  • 通过重新生成客户端密钥端点

使用服务帐户

每个 OIDC 客户端都有一个内置的服务帐户。 使用此服务帐户获取访问令牌。

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 选择您的客户端。

  3. 单击设置选项卡。

  4. 客户端身份验证切换为开启

  5. 选择服务帐户角色

  6. 点击 保存

  7. 配置您的客户端凭据

  8. 单击 Scope(范围) 选项卡。

  9. 验证您是否具有角色,或将允许完整范围切换为开启

  10. 单击服务帐户角色选项卡

  11. 为您的客户端配置可用于此服务帐户的角色。

来自访问令牌的角色是以下项的交集:

  • 客户端的角色范围映射与从链接的客户端范围继承的角色范围映射相结合。

  • 服务帐户角色。

要调用的 REST URL 是 /realms/{realm-name}/protocol/openid-connect/token。 此 URL 必须作为 POST 请求调用,并且要求您在请求中发布客户端凭据。

默认情况下,客户端凭据由客户端的 clientId 和 clientSecret 在 Authorization: Basic 标头中表示,但您也可以使用签名的 JWT 断言或任何其他自定义客户端身份验证机制对客户端进行身份验证。

您还需要按照 OAuth2 规范将 grant_type 参数设置为“client_credentials”。

例如,检索服务帐户的 POST 调用可能如下所示

    POST /realms/demo/protocol/openid-connect/token
    Authorization: Basic cHJvZHVjdC1zYS1jbGllbnQ6cGFzc3dvcmQ=
    Content-Type: application/x-www-form-urlencoded

    grant_type=client_credentials

响应将类似于 OAuth 2.0 规范中的此访问令牌响应

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
    "access_token":"2YotnFZFEjr1zCsicMWpAA",
    "token_type":"bearer",
    "expires_in":60
}

默认情况下,仅返回访问令牌。 默认情况下,不返回刷新令牌,并且在 Keycloak 端不会创建用户会话。 由于缺少刷新令牌,因此在访问令牌过期时需要重新身份验证。 但是,这种情况并不意味着 Keycloak 服务器有任何额外的开销,因为默认情况下不会创建会话。

在这种情况下,注销是不必要的。 但是,可以通过向 OAuth2 撤销端点发送请求来撤销已颁发的访问令牌,如OpenID Connect 端点部分所述。

附加资源

有关更多详细信息,请参阅客户端凭据授权

令牌中的角色映射

当用户进行身份验证时,会将一些角色添加到访问令牌中。 默认情况下,领域角色添加到访问令牌的 realm_access 声明中。 默认情况下,客户端角色添加到 resource_access 声明中。

添加到令牌的角色是以下项的交集:

分配给用户的角色

分配给用户的角色可以在角色映射中定义,如此节中所述。 少量细节:

  • 如果用户是某些的成员,则也会应用这些组的所有角色。

  • 如果角色是复合角色,则也会应用复合角色的子角色。 在令牌中,角色列表将展开,并包含所有角色。

  • 如果经过身份验证的用户不是普通用户,而是服务帐户(代表客户端),则使用服务帐户角色。 服务帐户角色在特定客户端的“服务帐户角色”选项卡中定义。

角色协议映射器

与其他声明类似,角色通过专用的协议映射器添加到为客户端颁发的访问令牌中。 领域中定义了一个内置客户端范围角色。 由于它是领域默认客户端范围,因此默认情况下将其定义为每个领域客户端的默认客户端范围。 您可以通过查看“客户端范围”选项卡,然后查找角色客户端范围,在管理控制台中看到此客户端范围。 此客户端范围默认包含以下协议映射器:

  • 协议映射器领域角色 - 此协议映射器用于将领域角色添加到令牌声明中。 默认情况下,配置如下所示:

领域角色映射器

mapper oidc realm roles

  • 协议映射器客户端角色 - 此协议映射器用于将客户端角色添加到令牌声明中。 默认情况下,配置如下所示:

客户端角色映射器

mapper oidc client roles

  • 协议映射器受众解析 - 此协议映射器用于根据应用的客户端角色填充访问令牌中的 aud 声明。 有关此映射器的详细信息,请参见受众解析部分

正如您在领域角色和客户端角色映射器的配置中看到的那样,可以配置:

  • 角色是仅添加到访问令牌,还是也添加到其他令牌,例如 ID 令牌。 默认情况下,角色添加到访问令牌和内省端点。

  • 角色将添加到哪些声明中。 默认情况下,领域角色添加到 realm_access 声明中。 因此,例如,包含 2 个领域角色 role1role2 的 JWT 令牌中的声明将类似于这样:

    "realm_access": {
      "roles": [ "role1", "role2" ]
    }

    默认情况下,客户端角色添加到 resource_access 令牌声明中。 此声明在令牌中将如下所示,其中包含客户端 account 的客户端角色 manage-accountmanage-account-links 以及客户端 target-client1 的客户端角色 target-client1-role

    "resource_access": {
      "target-client1": {
        "roles": [ "target-client1-role" ]
      },
      "account": {
        "roles": [ "manage-account", "manage-account-links" ]
      }
    }

通过调整角色协议映射器的“令牌声明名称”配置选项,可以指定将这些角色添加到令牌中的配置声明中。

如果您只想为一个特定客户端更新角色声明(例如,客户端 foo 希望领域角色在声明 my-realm-roles 中而不是声明 realm_access 中),则可以从您的客户端中删除默认客户端范围角色,而是在您的客户端的专用客户端范围中配置领域/客户端协议映射器。

示例

受众文档包含更详细的示例,其中涵盖了有关角色映射以及添加到令牌的受众(声明 aud)的一些详细信息。 此外,尝试客户端范围评估以查看在为特定客户端颁发令牌时使用的有效范围、协议映射器和角色范围映射,以及对于用户、客户端和应用的客户端范围的特定组合,JWT 令牌的外观如何,也可能很有用。

受众支持

通常,Keycloak 的部署环境由一组机密公共客户端应用程序组成,这些应用程序使用 Keycloak 进行身份验证。 这些客户端是前端客户端,可以直接将用户重定向到 Keycloak 以请求浏览器身份验证。 然后,特定客户端将在成功身份验证后收到一组令牌。

服务OAuth 2 规范中的资源服务器)也可用,它们为来自客户端应用程序的请求提供服务,并向这些应用程序提供资源。 这些服务需要从前端应用程序或其他服务发送给它们的访问令牌(Bearer 令牌)来验证请求的身份。

必须注意确保访问令牌具有有限的权限,并且特定访问令牌不会被服务滥用以访问其他第三方服务。 在服务之间信任度较低的环境中,您可能会遇到以下示例场景:

  1. 前端客户端应用程序 frontend-client 需要针对 Keycloak 进行身份验证。

  2. Keycloak 验证用户身份。

  3. Keycloak 向应用程序 frontend-client 颁发令牌。

  4. frontend-client 应用程序使用令牌来调用服务 service1

  5. service1 服务将响应返回给应用程序。 但假设此服务将尝试滥用令牌并将其保留以供进一步使用。

  6. 然后,service1 使用先前发送给它的应用程序令牌调用另一个服务 service2service2 不检查令牌是否不应该用于调用它,它将为请求提供服务并返回成功响应。 这会导致安全性被破坏,因为 service1 滥用令牌以代表客户端应用程序 frontend-client 访问其他服务。

这种情况在服务之间具有高度信任的环境中不太可能发生,但在信任度较低的环境中则不然。

为了防止对访问令牌的任何滥用,访问令牌可以包含声明 aud,该声明表示受众。 声明 aud 通常应表示令牌应该使用的所有服务的客户端 ID。 在服务之间信任度较低的环境中,建议:

  • 限制令牌上的受众,以确保访问令牌仅包含有限数量的受众。

  • 配置您的服务以验证令牌上的受众。

为了防止上面示例中的 service1 滥用令牌,安全流程的变体可能如下所示:

  1. 前端应用程序 frontend-client 针对 Keycloak 进行身份验证。

  2. Keycloak 验证用户身份。

  3. Keycloak 向 frontend-client 应用程序颁发令牌。 frontend-client 知道它将需要调用 service1,因此它在发送到 Keycloak 的身份验证请求中放置 scope=service1-scope。 范围 service1-scope 是一个客户端范围,可能需要由管理员创建。 在以下部分中,有一些关于如何设置此类客户端范围的选项。 令牌声明将如下所示:

    "aud": "service1"

    这声明客户端可以使用此访问令牌来调用 service1

  4. frontend-client 应用程序使用令牌来调用服务 service1

  5. service1 为客户端应用程序 frontend-application 的请求提供服务。 但假设此服务将尝试滥用令牌并将其保留以供进一步使用。

  6. 然后,service1 将尝试使用令牌调用 service2。 调用不成功,因为 service2 服务检查令牌上的受众,并发现其受众仅针对 service1。 因此,service2 将拒绝该请求,并将错误返回给 service1。 此行为是预期的,并且安全性不会被破坏。

服务调用另一个服务的能力

在某些环境中,可能需要 service1service2 检索其他数据,以将数据返回给原始客户端应用程序 frontend-client。 为了使此功能正常工作,有几种可能性:

  • 确保颁发给 frontend-client 的初始访问令牌将同时包含 service1service2 作为受众。 假设设置了正确的客户端范围,frontend-client 可以使用 scope=service1-scope service2-scope 作为 scope 参数的值。 然后,颁发的令牌将包含 aud 声明,如下所示:

    "aud": [ "service1", "service2" ]

    这样的访问令牌可以用于调用 service1service2。 因此,service1 将能够成功使用此类令牌来调用 service2 以检索其他数据。

  • 之前的在令牌受众中同时包含两个服务的方法允许 service1 调用 service2。然而,这也意味着 frontend-client 也可以直接使用其访问令牌来调用 service2。这在某些情况下可能是不希望发生的。您可能希望 service1 能够调用 service2,但同时,您不希望 frontend-client 能够直接调用 service2。针对这种情况的解决方案可能是使用 令牌交换。在这种情况下,初始令牌仍然只将 service1 作为受众。但是,一旦令牌被发送到 service1service1 可以发送令牌交换请求来交换另一个令牌,该令牌将把 service2 作为受众。有关如何使用令牌交换的详细信息,请参阅 令牌交换文档

设置

当设置受众检查时

  • 确保服务配置为检查发送给它们的访问令牌上的受众。这可以通过特定于您客户端 OIDC 适配器的方式完成,您正在使用该适配器来保护您的 OIDC 客户端应用程序。

  • 确保 Keycloak 颁发的访问令牌包含所有必要的受众。

    可以通过两种方式将受众添加到令牌

基于客户端角色自动添加受众

在默认客户端作用域roles中定义了一个受众解析协议映射器。该映射器检查是否有客户端至少有一个可用于当前令牌的客户端角色。然后,每个此类客户端的客户端 ID 将被添加为受众,如果您的服务客户端依赖于客户端角色,这将非常有用。服务客户端通常可以是没有任何启用流程的客户端,它可能没有直接向自身颁发任何令牌。它代表 OAuth 2 资源服务器

令牌角色映射部分包含有关如何将客户端角色添加到令牌的详细信息。另请参阅下面的示例。

示例 - 令牌角色映射和受众声明

以下是如何使用客户端角色使 aud 声明添加到令牌的示例步骤

  1. 创建一个 OIDC 客户端 service1。可以禁用此客户端的标准流程或任何其他流程,因为它是一个服务客户端,可能永远不会自行直接进行身份验证。如果需要,标准令牌交换开关可能是例外情况,如上所述。

  2. 转到该客户端的角色选项卡,并创建客户端角色 service1-role

  3. 在同一域中创建用户 john,并将客户端 service1 的客户端角色 service1-role 分配给他。 此部分包含有关如何执行此操作的一些详细信息。

  4. 创建名为 service1-scope 的客户端作用域。可以将其标记为包含在令牌作用域中开启。有关如何创建和设置新客户端作用域的详细信息,请参阅 此部分

  5. 转到 service1-scope作用域选项卡,并将客户端 service1 的角色 service1-role 添加到此客户端作用域的 角色作用域映射

  6. 在域中创建另一个客户端 frontend-client

  7. 单击此客户端的客户端作用域选项卡,选择第一个专用客户端作用域 frontend-client-dedicated,然后转到作用域选项卡并禁用允许全部作用域开关

  8. 返回此客户端的客户端作用域选项卡,然后单击添加客户端作用域,并将 service1-scope 链接为可选。有关更多详细信息,请参阅 客户端作用域链接部分

  9. 单击 客户端作用域 中的子选项卡评估,如 此部分 中所述。当填写用户 john 和子选项卡 生成的访问令牌时,可以看到没有任何 aud 声明,因为在生成的示例令牌中没有任何客户端角色。但是,当也将作用域 service1-scope 添加到作用域字段时,可以看到客户端角色 service1-role,因为它在 service1-scope角色作用域映射中,并且也在用户 john 的角色映射中。因此,aud 声明也将包含 service1

受众解析示例

audience resolving evaluate

如果您希望始终将 service1 受众应用于颁发给 frontend-client 客户端的令牌(不使用参数 scope=service1-scope),那么可以执行以下任一操作

  • service1-scope 分配为默认客户端作用域,而不是可选客户端作用域

  • service1-role 的角色作用域映射直接添加到客户端的 专用客户端作用域。在这种情况下,您将完全不需要 service1-scope

请注意,由于此方法基于客户端角色,因此它还需要用户本身(以上示例中的用户 john)是客户端 service1 的某些客户端角色的成员。否则,如果没有分配任何客户端角色,则不会包含受众 service1。如果您希望无论客户端角色如何都包含受众,请参阅 硬编码受众 部分。

前端客户端本身不会自动添加到访问令牌受众中,因此可以轻松区分访问令牌和 ID 令牌,因为访问令牌不会包含为其颁发令牌的客户端作为受众。

如果您需要将客户端本身作为受众,请参阅 硬编码受众 选项。但是,不建议将同一客户端同时用作前端和 REST 服务。

硬编码受众

当您的服务依赖于域角色或根本不依赖于令牌中的角色时,使用硬编码受众可能很有用。硬编码受众是一个协议映射器,它会将指定服务客户端的客户端 ID 作为受众添加到令牌中。如果您想使用与客户端 ID 不同的受众,可以使用任何自定义值,例如 URL。

您可以直接将协议映射器添加到前端客户端。如果直接添加协议映射器,则始终会添加受众。

为了更好地控制协议映射器,您可以在专用客户端作用域上创建协议映射器,例如,可以将其命名为 service2

以下是硬编码受众的示例步骤

  1. 创建一个客户端 service2

  2. 创建一个客户端作用域 service2-scope

  3. 在该客户端作用域的映射器选项卡中,选择配置新映射器,然后选择受众

  4. 选择包含的客户端受众service2,然后保存映射器

    受众协议映射器

    audience mapper

  5. 将新创建的客户端作用域与某些客户端链接。例如,它可以作为可选客户端作用域链接到 上一个示例 中创建的客户端 frontend-client

  6. 您可以选择为链接了客户端作用域的客户端(例如 frontend-client评估客户端作用域并生成示例访问令牌。如果 service2-scope 包含在 scope 参数中(当您将其分配为可选客户端作用域时),则受众 service2 将添加到生成的访问令牌的受众中。

在您的机密客户端应用程序中,确保使用了 scope 参数。当您要颁发用于访问 service2 的令牌时,必须包含类似 scope=service2-scope 的值。

如果您的应用程序使用 javascript 适配器,请参阅 Keycloak JavaScript 适配器 部分,了解如何发送带有期望值的 scope 参数。

如果您希望在请求中不包含 scope 参数,则可以将 service2-scope 链接为默认客户端作用域,或者使用您在其中配置此映射器的客户端专用作用域。如果您希望始终为 OIDC 客户端 frontend-client 的所有身份验证请求应用受众,这将非常有用。

默认情况下,受众受众解析协议映射器仅将受众添加到访问令牌。ID 令牌通常仅包含单个受众,即为其颁发令牌的客户端 ID,这是 OpenID Connect 规范的要求。但是,访问令牌不一定具有为其颁发令牌的客户端 ID,除非 受众 映射器添加了它。

创建 SAML 客户端

Keycloak 支持 SAML 2.0 用于注册的应用程序。支持 POST 和重定向绑定。您可以选择要求客户端签名验证。您也可以让服务器对响应进行签名和/或加密。

步骤
  1. 单击菜单中的 Clients(客户端)。

  2. 单击创建客户端以转到创建客户端页面。

  3. 客户端类型设置为 SAML

    创建客户端

    add client saml

  4. 输入客户端的 客户端 ID。这通常是一个 URL,并且是应用程序发送的 SAML 请求中期望的 issuer 值。

  5. 单击保存。此操作将创建客户端并将您带到设置选项卡。

以下部分描述了此选项卡上的每个设置。

设置选项卡

设置 选项卡包含许多用于配置此客户端的选项。

客户端设置

client settings saml

常规设置
客户端 ID

字母数字 ID 字符串,用于 OIDC 请求和 Keycloak 数据库中以标识客户端。此值必须与 AuthNRequests 发送的 issuer 值匹配。Keycloak 从 Authn SAML 请求中提取 issuer,并通过此值将其与客户端匹配。

名称

Keycloak UI 屏幕中客户端的名称。要本地化名称,请设置替换字符串值。例如,字符串值如 ${myapp}。有关更多信息,请参阅 服务器开发者指南

描述

客户端的描述。此设置也可以本地化。

始终在控制台中显示

即使此用户没有活动会话,也始终在帐户控制台中列出此客户端。

访问设置
根 URL

当 Keycloak 使用配置的相对 URL 时,此值将前置到 URL。

主页 URL

如果 Keycloak 需要链接到客户端,则使用此 URL。

有效重定向 URI

输入 URL 模式,然后单击 + 号添加。单击 - 号删除。单击保存以保存这些更改。通配符值仅允许在 URL 的末尾。例如,http://host.com/*$$。当未注册确切的 SAML 端点且 Keycloak 从请求中提取断言消费者 URL 时,将使用此字段。

IDP 发起的 SSO URL 名称

当您要执行 IDP 发起的 SSO 时,引用客户端的 URL 片段名称。将此项留空将禁用 IDP 发起的 SSO。您将从浏览器引用的 URL 将是:server-root/realms/{realm-name}/protocol/saml/clients/{client-url-name}

IDP 发起的 SSO 中继状态

当您要执行 IDP 发起的 SSO 时,您希望与 SAML 请求一起发送的中继状态。

主 SAML 处理 URL

此 URL 用于所有 SAML 请求,并且响应将定向到 SP。它用作断言消费者服务 URL 和单点注销服务 URL。

如果登录请求包含断言消费者服务 URL,则这些登录请求将优先。此 URL 必须通过注册的有效重定向 URI 模式进行验证。

SAML 能力
名称 ID 格式

主题的名称 ID 格式。如果在请求中未指定名称 ID 策略,或者将强制名称 ID 格式属性设置为“开启”,则使用此格式。

强制名称 ID 格式

如果请求具有名称 ID 策略,则忽略它,并使用在管理控制台中名称 ID 格式下配置的值。

强制 POST 绑定

默认情况下,Keycloak 使用原始请求的初始 SAML 绑定进行响应。通过启用强制 POST 绑定,即使原始请求使用了重定向绑定,Keycloak 也使用 SAML POST 绑定进行响应。

强制 artifact 绑定

如果启用,响应消息将通过 SAML ARTIFACT 绑定系统返回到客户端。

包含 AuthnStatement

SAML 登录响应可以指定使用的身份验证方法,例如密码,以及登录和会话过期的的时间戳。Include AuthnStatement 默认启用,以便 AuthnStatement 元素将包含在登录响应中。将其设置为 OFF 会阻止客户端确定最大会话时长,这可能会创建永不过期的客户端会话。

包含 OneTimeUse 条件

如果启用,则 OneTimeUse 条件将包含在登录响应中。

优化 REDIRECT 签名密钥查找

当设置为 ON 时,SAML 协议消息将包含 Keycloak 原生扩展。此扩展包含签名密钥 ID 的提示。SP 使用此扩展进行签名验证,而不是尝试使用密钥验证签名。

此选项适用于 REDIRECT 绑定,其中签名在查询参数中传输,并且在签名信息中找不到此信息。这与 POST 绑定消息相反,在 POST 绑定消息中,密钥 ID 始终包含在文档签名中。

当 Keycloak 服务器和适配器提供 IDP 和 SP 时,将使用此选项。此选项仅在 Sign Documents 设置为 ON 时相关。

签名和加密
签署文档

当设置为 ON 时,Keycloak 使用 realm 的私钥签署文档。

签署断言

断言已签名并嵌入在 SAML XML Auth 响应中。

签名算法

用于签署 SAML 文档的算法。请注意,基于 SHA1 的算法已被弃用,并可能在未来的版本中删除。我们建议使用比 *_SHA1 更安全的算法。此外,对于 *_SHA1 算法,如果 SAML 客户端在 Java 17 或更高版本上运行,则验证签名将不起作用。

SAML 签名密钥名称

使用 POST 绑定发送的已签名 SAML 文档在 KeyName 元素中包含签名密钥的标识。此操作可以通过 SAML Signature Key Name 选项控制。此选项控制 Keyname 的内容。

  • KEY_ID KeyName 包含密钥 ID。此选项为默认选项。

  • CERT_SUBJECT KeyName 包含来自与 realm 密钥对应的证书的主题。Microsoft Active Directory Federation Services 期望使用此选项。

  • NONE KeyName 提示将完全从 SAML 消息中省略。

规范化方法

XML 签名的规范化方法。

登录设置
登录主题

用于登录、OTP、授权注册和忘记密码页面的主题。

需要同意

如果启用,用户必须同意客户端访问。

对于执行浏览器登录的客户端客户端。由于无法确保客户端客户端的密钥安全,因此通过配置正确的重定向 URI 来限制访问非常重要。

在屏幕上显示客户端

此开关在 需要同意关闭 时适用。

  • 关闭

    同意屏幕将仅包含与配置的客户端作用域相对应的同意项。

  • 开启

    同意屏幕上还将有一个关于此客户端本身的条目。

客户端同意屏幕文本

需要同意在屏幕上显示客户端 都启用时适用。包含同意屏幕上关于此客户端权限的文本。

注销设置
前端通道注销

如果启用 Front Channel Logout,则应用程序需要浏览器重定向来执行注销。例如,应用程序可能需要重置 cookie,这只能通过重定向完成。如果禁用 Front Channel Logout,Keycloak 将调用后台 SAML 请求以注销应用程序。

密钥选项卡

加密断言

使用 realm 的私钥加密 SAML 文档中的断言。AES 算法使用 128 位密钥大小。

客户端签名必需

如果启用 Client Signature Required,则来自客户端的文档应进行签名。Keycloak 将使用在“密钥”选项卡中设置的客户端公钥或证书来验证此签名。

允许 ECP 流

如果为 true,则允许此应用程序使用 SAML ECP 配置文件进行身份验证。

高级选项卡

此选项卡有许多用于特定情况的字段。某些字段在其他主题中介绍。有关其他字段的详细信息,请单击问号图标。

精细粒度 SAML 端点配置
Logo URL

引用客户端应用程序 Logo 的 URL。

策略 URL

依赖方客户端向最终用户提供的 URL,用于阅读有关如何使用个人资料数据的说明。

服务条款 URL

依赖方客户端向最终用户提供的 URL,用于阅读有关依赖方服务条款的说明。

Assertion Consumer Service POST 绑定 URL

Assertion Consumer Service 的 POST 绑定 URL。

Assertion Consumer Service Redirect 绑定 URL

Assertion Consumer Service 的 Redirect 绑定 URL。

Logout Service POST 绑定 URL

Logout Service 的 POST 绑定 URL。

Logout Service Redirect 绑定 URL

Logout Service 的 Redirect 绑定 URL。

Logout Service Artifact 绑定 URL

Logout Service 的 Artifact 绑定 URL。当与“强制 Artifact 绑定”选项一起设置时,登录和注销流程都将强制使用 Artifact 绑定。除非设置此属性,否则注销不会使用 Artifact 绑定。

Logout Service SOAP 绑定 URL

Logout Service 的 Redirect 绑定 URL。仅在使用 back channel logout 时适用。

Artifact 绑定 URL

用于发送 HTTP artifact 消息的 URL。

Artifact Resolution Service

客户端 SOAP 端点的 URL,用于向其发送 ArtifactResolve 消息。

IDP 发起的登录

IDP 发起的登录是一项功能,允许您在 Keycloak 服务器上设置一个端点,该端点将使您登录到特定的应用程序/客户端。在客户端的设置选项卡中,您需要指定IDP Initiated SSO URL Name。这是一个简单的字符串,其中不包含空格。之后,您可以使用以下 URL 引用您的客户端:root/realms/{realm-name}/protocol/saml/clients/{url-name}

IDP 发起的登录实现优先选择 POST 绑定而不是 REDIRECT 绑定(有关更多信息,请查看 saml 绑定)。因此,最终的绑定和 SP URL 按以下方式选择

  1. 如果定义了特定的 Assertion Consumer Service POST Binding URL(在客户端设置的**精细粒度 SAML 端点配置**部分内),则通过该 URL 使用 POST 绑定。

  2. 如果指定了通用的 Master SAML Processing URL,则再次在此通用 URL 中使用 POST 绑定。

  3. 作为最后的手段,如果配置了 Assertion Consumer Service Redirect Binding URL(在**精细粒度 SAML 端点配置**内),则使用 REDIRECT 绑定和此 URL。

如果您的客户端需要特殊的 relay state,您也可以在**设置**选项卡中的 IDP Initiated SSO Relay State 字段中配置它。或者,浏览器可以在 RelayState 查询参数中指定 relay state,例如 root/realms/{realm-name}/protocol/saml/clients/{url-name}?RelayState=thestate

当使用 身份代理 时,可以为来自外部 IDP 的客户端设置 IDP 发起的登录。实际客户端在代理 IDP 中设置为 IDP 发起的登录,如上所述。外部 IDP 必须为应用程序 IDP 发起的登录设置客户端,该登录将指向一个特殊的 URL,该 URL 指向代理并表示代理 IDP 中所选客户端的 IDP 发起的登录端点。这意味着在外部 IDP 的客户端设置中

  • IDP Initiated SSO URL Name 设置为将作为 IDP 发起的登录初始点发布的名称,

  • Assertion Consumer Service POST Binding URL 在**精细粒度 SAML 端点配置**部分中必须设置为以下 URL:broker-root/realms/{broker-realm}/broker/{idp-name}/endpoint/clients/{client-id},其中

    • broker-root 是基础代理 URL

    • broker-realm 是声明外部 IDP 的代理中的 realm 名称

    • idp-name 是代理中外部 IDP 的名称

    • client-id 是在代理中定义的 SAML 客户端的 IDP Initiated SSO URL Name 属性的值。正是此客户端将可用于来自外部 IDP 的 IDP 发起的登录。

请注意,您可以将基本客户端设置从代理 IDP 导入到外部 IDP 的客户端设置中 - 只需使用代理 IDP 中身份提供程序的设置中提供的 SP 描述符,并将 clients/client-id 添加到端点 URL。

使用实体描述符创建客户端

除了手动注册 SAML 2.0 客户端之外,您还可以使用标准的 SAML 实体描述符 XML 文件导入客户端。

“客户端”页面包含导入客户端选项。

添加客户端

Import SAML client

步骤
  1. 单击浏览

  2. 加载包含 XML 实体描述符信息的文件。

  3. 检查信息以确保一切设置正确。

某些 SAML 客户端适配器(例如 mod-auth-mellon)需要 IDP 的 XML 实体描述符。您可以通过访问此 URL 找到此描述符

root/realms/{realm-name}/protocol/saml/descriptor

其中 realm 是您的客户端的 realm。

为了从一个客户端链接到另一个客户端,Keycloak 提供了一个重定向端点:/realms/realm_name/clients/{client-id}/redirect

如果客户端使用 HTTP GET 请求访问此端点,则 Keycloak 以 HTTP 307(临时重定向)的形式在响应的 Location 标头中返回为提供的客户端和 Realm 配置的基本 URL。因此,客户端只需要知道 Realm 名称和客户端 ID 即可链接到它们。这种间接方式避免了硬编码客户端基本 URL。

例如,给定 realm master 和客户端 ID account

http://host:port/realms/master/clients/account/redirect

此 URL 临时重定向到:http://host:port/realms/master/account

OIDC 令牌和 SAML 断言映射

接收 ID 令牌、访问令牌或 SAML 断言的应用程序可能需要不同的角色和用户元数据。

您可以使用 Keycloak 来

  • 硬编码角色、声明和自定义属性。

  • 将用户元数据拉入令牌或断言。

  • 重命名角色。

您可以在管理控制台的**映射器**选项卡中执行这些操作。

映射器选项卡

mappers oidc

新客户端没有内置映射器,但它们可以从客户端作用域继承一些映射器。有关更多详细信息,请参阅 客户端作用域部分

协议映射器将项目(例如电子邮件地址)映射到身份和访问令牌中的特定声明。映射器的功能应该从其名称中不言自明。您可以通过单击**添加内置**来添加预配置的映射器。

每个映射器都有一组通用设置。其他设置取决于映射器类型。单击映射器旁边的**编辑**以访问配置屏幕来调整这些设置。

映射器配置

mapper config

可以通过将鼠标悬停在其工具提示上来查看每个选项的详细信息。

您可以使用大多数 OIDC 映射器来控制声明的放置位置。您可以选择通过调整**添加到 ID 令牌**和**添加到访问令牌**开关,将声明包含在 idaccess 令牌中或从中排除。

您可以按如下方式添加映射器类型

步骤
  1. 转到**映射器**选项卡。

  2. 单击**配置新映射器**。

    添加映射器

    add mapper

  3. 从列表框中选择**映射器类型**。

优先级顺序

映射器实现具有优先级顺序优先级顺序不是映射器的配置属性。它是映射器具体实现的属性。

Mapper 按照 mapper 列表中的顺序排序。令牌或断言中的更改按照此顺序应用,顺序靠前的 mapper 先应用。因此,依赖于其他实现的实现会按照必要的顺序进行处理。

例如,要计算将包含在令牌中的角色

  1. 基于这些角色解析受众。

  2. 处理 JavaScript 脚本,该脚本使用令牌中已有的角色和受众。

OIDC 用户会话备注 Mapper

用户会话详细信息使用 mapper 定义,并在您在客户端上使用或启用功能时自动包含。单击添加内置以包含会话详细信息。

模拟用户会话提供以下详细信息

  • IMPERSONATOR_ID:模拟用户的 ID。

  • IMPERSONATOR_USERNAME:模拟用户的用户名。

服务帐户会话提供以下详细信息

  • clientId:服务帐户的客户端 ID。

  • client_id:服务帐户的客户端 ID。

  • clientAddress:服务帐户的已验证设备的远程主机 IP。

  • clientHost:服务帐户的已验证设备的远程主机名。

脚本 Mapper

使用脚本 Mapper 通过运行用户定义的 JavaScript 代码将声明映射到令牌。有关将脚本部署到服务器的更多详细信息,请参阅JavaScript 提供程序

当脚本部署后,您应该能够从可用 mapper 列表中选择已部署的脚本。

成对主体标识符 Mapper

默认情况下,主体声明 sub 由默认客户端作用域 basic 中的 Subject (sub) 协议 Mapper 映射。

要使用成对主体标识符(通过使用诸如 Pairwise subject identifier 之类的协议 Mapper),您可以从 basic 客户端作用域中删除 Subject (sub) 协议 Mapper。但这并非严格必要,因为 Subject (sub) 协议 Mapper 在 Pairwise subject identifier Mapper 之前执行,因此成对值将覆盖 Subject Mapper 添加的值。这是由于 Subject Mapper 的优先级。因此,删除内置的 Subject (sub) Mapper 的唯一优势可能是通过避免使用协议 Mapper 来节省少量性能,但这可能没有任何效果。

使用轻量级访问令牌

Keycloak 中的访问令牌包含敏感信息,包括个人身份信息 (PII)。因此,如果资源服务器不想向客户端等第三方实体泄露此类信息,Keycloak 支持从访问令牌中删除 PII 的轻量级访问令牌。此外,当资源服务器获取从访问令牌中删除的 PII 时,它可以通过将访问令牌发送到 Keycloak 的令牌自省端点来获取 PII。

无法从轻量级访问令牌中删除的信息

协议 Mapper 可以控制哪些信息放入访问令牌,轻量级访问令牌也使用协议 Mapper。因此,以下信息无法从轻量级访问令牌中删除。
expiatjtiisstypazpsidscopecnf

在 Keycloak 中使用轻量级访问令牌

通过将 客户端策略use-lightweight-access-token 执行器应用于客户端,客户端可以接收轻量级访问令牌而不是访问令牌。轻量级访问令牌包含由协议 Mapper 控制的声明,其设置添加到轻量级访问令牌(默认为关闭)已开启。此外,通过开启协议 Mapper 的设置添加到令牌自省,客户端可以通过将访问令牌发送到 Keycloak 的令牌自省端点来获取声明。

自省端点

在某些情况下,使用 HTTP 标头 Accept: application/jwt 而不是 Accept: application/json 触发令牌自省端点可能很有用,这对于轻量级访问令牌尤其有用。有关令牌自省端点的详细信息,请参阅保护应用部分。

生成客户端适配器配置

Keycloak 可以生成配置文件,您可以使用这些文件在应用程序的部署环境中安装客户端适配器。OIDC 和 SAML 支持多种适配器类型。

  1. 单击操作菜单,然后选择 下载适配器配置 选项

    client installation

  2. 选择您要为其生成配置的 格式选项

支持所有用于 OIDC 和 SAML 的 Keycloak 客户端适配器。mod-auth-mellon Apache HTTPD 适配器(用于 SAML)以及标准 SAML 实体描述符文件也受支持。

客户端作用域

使用 Keycloak 在名为客户端作用域的实体中定义共享客户端配置。客户端作用域 为多个客户端配置协议 Mapper角色作用域映射

客户端作用域还支持 OAuth 2 scope 参数。客户端应用程序使用此参数来请求访问令牌中的声明或角色,具体取决于应用程序的需求。

要创建客户端作用域,请按照以下步骤操作

  1. 在菜单中单击 客户端作用域

    客户端作用域列表

    client scopes list

  2. 单击“创建”。

  3. 命名您的客户端作用域。

  4. 点击 保存

客户端作用域具有与常规客户端类似的选项卡。您可以定义协议 Mapper角色作用域映射。这些映射可以由其他客户端继承,并配置为从该客户端作用域继承。

协议

创建客户端作用域时,选择协议。链接到同一作用域的客户端必须具有相同的协议。

每个 realm 在菜单中都有一组预定义的内置客户端作用域。

  • SAML 协议:role_list。此作用域包含一个用于 SAML 断言中角色列表的协议 Mapper。

  • OpenID Connect 协议:有多个可用的客户端作用域

    • 角色

      此作用域未在 OpenID Connect 规范中定义,并且不会自动添加到访问令牌中的 scope 声明中。此作用域具有 mapper,这些 mapper 用于将用户的角色添加到访问令牌,并为至少具有一个客户端角色的客户端添加受众。这些 mapper 在令牌角色映射部分受众部分中进行了更详细的描述。

    • web-origins

      此作用域也未在 OpenID Connect 规范中定义,并且未添加到访问令牌的 scope 声明中。此作用域用于将允许的 Web 源添加到访问令牌 allowed-origins 声明中。

    • microprofile-jwt

      此作用域处理 MicroProfile/JWT 身份验证规范 中定义的声明。此作用域为 upn 声明定义了用户属性 mapper,为 groups 声明定义了 realm 角色 mapper。可以更改这些 mapper,以便可以使用不同的属性来创建 MicroProfile/JWT 特定声明。

    • offline_access

      当客户端需要获取离线令牌时,使用此作用域。有关离线令牌的更多详细信息,请参见离线访问部分OpenID Connect 规范

    • profile

    • email

    • address

    • phone

客户端作用域 profileemailaddressphoneOpenID Connect 规范 中定义。这些作用域没有定义任何角色作用域映射,但它们确实定义了协议 Mapper。这些 Mapper 对应于 OpenID Connect 规范中定义的声明。

例如,当您打开 phone 客户端作用域并打开 Mapper 选项卡时,您将看到与 phone 作用域规范中定义的声明相对应的协议 Mapper。

客户端作用域 Mapper

client scopes phone

phone 客户端作用域链接到客户端时,客户端会自动继承 phone 客户端作用域中定义的所有协议 Mapper。为此客户端颁发的访问令牌包含有关用户的电话号码信息,前提是用户已定义电话号码。

内置客户端作用域包含规范中定义的协议 Mapper。您可以自由编辑客户端作用域,并创建、更新或删除任何协议 Mapper 或角色作用域映射。

客户端作用域包含与同意屏幕相关的选项。如果链接的客户端在客户端上启用了需要同意,则这些选项非常有用。

在同意屏幕上显示

如果启用了在同意屏幕上显示,并且该作用域已添加到需要同意的客户端,则 同意屏幕文本 中指定的文本将显示在同意屏幕上。此文本在用户通过身份验证后以及在用户从 Keycloak 重定向到客户端之前显示。如果禁用在同意屏幕上显示,则此客户端作用域将不会显示在同意屏幕上。

同意屏幕文本

当此客户端作用域添加到需要同意的客户端时,同意屏幕上显示的文本默认为客户端作用域的名称。可以使用带有 ${var-name} 字符串的替换变量自定义此文本的值。自定义值在主题中的属性文件中配置。有关自定义的更多信息,请参见服务器开发者指南

包含在令牌作用域中

客户端作用域上有一个 包含在令牌作用域中 开关。如果打开,则此客户端作用域的名称将添加到访问令牌属性作用域,以及令牌响应和令牌自省端点响应声明 scope 中。如果关闭,则此客户端作用域将从令牌和令牌自省端点响应中省略。如上所述,某些内置客户端作用域已禁用此开关,这意味着即使它们应用于特定请求,也不会包含在 scope 声明中。

将客户端作用域与客户端链接

客户端作用域和客户端之间的链接在客户端的 客户端作用域 选项卡中配置。以下是客户端应用程序 myclient 的外观

链接到客户端的客户端作用域

client scopes default

客户端作用域和客户端之间有两种链接方式。

默认客户端作用域

此设置适用于 OpenID Connect 和 SAML 客户端。颁发客户端的 OpenID Connect 令牌或 SAML 断言时,将应用默认客户端作用域。客户端将继承客户端作用域上定义的协议 Mapper 和角色作用域映射。对于 OpenID Connect 协议,无论 OpenID Connect 授权请求中 scope 参数的值如何,始终应用 Mapper 和角色作用域映射。

可选客户端作用域

此设置仅适用于 OpenID Connect 客户端。仅当 OpenID Connect 授权请求中的 scope 参数请求时,才会在为此客户端颁发令牌时应用可选客户端作用域。

示例

对于此示例,假设客户端已将 profileemail 链接为默认客户端作用域,并将 phoneaddress 链接为可选客户端作用域。客户端在向 OpenID Connect 授权端点发送请求时使用 scope 参数的值。

scope=openid phone

scope 参数包含字符串,作用域值用空格分隔。值 openid 是用于所有 OpenID Connect 请求的元值。令牌将包含来自默认客户端作用域 profileemail 以及 phone(scope 参数请求的可选客户端作用域)的 mapper 和角色作用域映射。

专用客户端作用域

有一个特殊的客户端作用域,它链接到每个客户端。这是一个专用客户端作用域,当您单击特定客户端的 客户端作用域 选项卡时,它始终显示为第一个客户端作用域。例如,对于客户端 myclient,客户端作用域显示为 myclient-dedicated。此客户端作用域表示直接链接到客户端本身的协议 Mapper 和角色作用域映射。

无法从客户端取消链接专用客户端作用域。此外,也无法将此专用客户端作用域链接到其他客户端。换句话说,专用客户端作用域仅适用于特定于单个客户端的协议 Mapper 和角色作用域映射。如果您想在多个客户端之间共享相同的协议 Mapper 配置,通常最好在 realm 选项卡 客户端作用域 中创建一个客户端作用域,然后将此共享客户端作用域链接到每个应应用此共享配置的客户端。

在专用客户端作用域的 作用域 选项卡中,您可以定义适用于此客户端的角色作用域映射。您还可以在此选项卡中看到 允许完整作用域 开关。有关此开关的详细信息,请参见本节本节

在管理 REST API 和内部 Keycloak 存储中,专用客户端作用域并不作为独立实体存在,因为它的协议映射器和角色作用域映射在内部链接到客户端本身。专用客户端作用域实际上只是管理控制台 UI 的一个抽象概念。

评估客户端作用域

映射器 选项卡包含协议映射器,而 作用域 选项卡包含为此客户端声明的角色作用域映射。它们不包含从客户端作用域继承的映射器和作用域映射。可以查看有效的协议映射器(即在客户端本身以及从链接的客户端作用域继承的协议映射器)和在为客户端生成令牌时使用的有效角色作用域映射。

步骤
  1. 单击客户端的 客户端作用域 选项卡。

  2. 打开子选项卡 评估

  3. 选择要应用的可选客户端作用域。

这将同时显示 scope 参数的值。此参数需要从应用程序发送到 Keycloak OpenID Connect 授权端点。

如果您的应用程序使用 Keycloak JavaScript 适配器,请参阅其章节以了解如何发送具有所需值的 scope 参数。

您还可以模拟为此客户端颁发的访问令牌、ID 令牌或 UserInfo 响应对于特定选定用户以及 audience 参数的特定值的外观。请注意,audience 参数目前仅支持令牌交换授权。建议在模拟任何其他授权时将其留空。

评估客户端作用域

client scopes evaluate

所有示例都是为特定用户生成,并为特定客户端颁发,并带有 scope 参数的指定值。这些示例包括使用的所有声明和角色映射。

客户端作用域权限

当向用户颁发令牌时,客户端作用域仅在用户被允许使用它时才适用。

当客户端作用域没有任何角色作用域映射定义时,每个用户都被允许使用此客户端作用域。但是,当客户端作用域定义了角色作用域映射时,用户必须是至少一个角色的成员。用户角色与客户端作用域的角色之间必须存在交集。复合角色会被纳入评估此交集。

如果用户未被允许使用客户端作用域,则在生成令牌时将不会使用任何协议映射器或角色作用域映射。客户端作用域将不会出现在令牌的 scope 值中。

Realm 默认客户端作用域

使用 Realm 默认客户端作用域 来定义自动链接到新创建客户端的客户端作用域集合。

要查看 realm 默认客户端作用域,请单击管理控制台左侧的 客户端作用域 选项卡。在 分配类型 列中,您可以指定特定的客户端作用域应添加为新创建客户端的 默认客户端作用域 还是 可选客户端作用域 。有关 默认 可选 客户端作用域的详细信息,请参阅 此节

创建客户端时,如果需要,您可以取消链接默认客户端作用域。这类似于删除 默认角色

作用域解释

术语 作用域 在 Keycloak 和整个 OAuth/OIDC 规范中具有多种含义。以下是对 Keycloak 中使用的不同 作用域 的澄清

客户端作用域

客户端作用域是 Keycloak 中在 realm 级别配置并可以链接到客户端的实体。当请求发送到 Keycloak 授权端点并带有 scope 参数的相应值时,客户端作用域通过其名称引用。有关更多详细信息,请参阅 客户端作用域链接 部分。

角色作用域映射

这在客户端或客户端作用域的 作用域 选项卡下可用。使用 角色作用域映射 来限制可以在访问令牌中使用的角色。有关更多详细信息,请参阅 角色作用域映射 部分。

授权作用域

授权作用域 涵盖可在应用程序中执行的操作。有关更多详细信息,请参阅 授权服务指南

客户端策略

为了便于保护客户端应用程序的安全,以统一的方式实现以下几点是有益的。

  • 设置关于客户端可以拥有的配置的策略

  • 客户端配置的验证

  • 符合要求的安全标准和配置文件,例如金融级 API (FAPI) 和 OAuth 2.1

为了以统一的方式实现这些点,引入了 客户端策略 的概念。

用例

客户端策略实现了以下几点。

设置关于客户端可以拥有的配置的策略

客户端上的配置设置可以通过客户端策略在客户端创建/更新期间强制执行,也可以在与特定客户端相关的 OpenID Connect 请求期间对 Keycloak 服务器强制执行。Keycloak 还通过 客户端注册策略 支持类似的功能,该策略在 保护应用程序和服务指南 中的 客户端注册服务 中进行了描述。但是,客户端注册策略只能覆盖 OIDC 动态客户端注册。客户端策略不仅涵盖了客户端注册策略可以做的事情,还涵盖了其他客户端注册和配置方式。目前的计划是用客户端策略取代客户端注册。

客户端配置的验证

Keycloak 支持验证客户端是否遵循诸如代码交换的 Proof Key、请求对象签名算法、持有者密钥令牌等设置,以及诸如授权端点、令牌端点等端点。这些可以通过每个设置项(在管理控制台上、开关、下拉菜单等)指定。为了使客户端应用程序安全,管理员需要以适当的方式设置许多设置,这使得管理员难以保护客户端应用程序的安全。客户端策略可以执行上述客户端配置的验证,它们也可以用于自动配置某些客户端配置开关以满足高级安全要求。在未来,单个客户端配置设置可能会被直接执行所需验证的客户端策略所取代。

符合要求的安全标准和配置文件,例如 FAPI 和 OAuth 2.1

全局客户端配置文件 是 Keycloak 中默认预配置的客户端配置文件。它们预先配置为符合标准安全配置文件,例如 保护应用程序 部分中的 FAPI OAuth 2.1 ,这使得管理员可以轻松地保护其客户端应用程序以符合特定的安全配置文件。目前,Keycloak 具有用于支持 FAPI 和 OAuth 2.1 规范的全局配置文件。管理员只需配置客户端策略以指定哪些客户端应符合 FAPI 和 OAuth 2.1。管理员可以配置客户端配置文件和客户端策略,以便可以轻松地使 Keycloak 客户端符合各种其他安全配置文件,例如 SPA、原生应用程序、开放银行等。

协议

客户端策略概念独立于任何特定协议。Keycloak 当前特别支持 OpenID Connect (OIDC) 协议 的客户端配置文件,但也提供了 SAML 协议 的客户端配置文件。

架构

客户端策略由四个构建块组成:条件、执行器、配置文件和策略。

条件

条件确定策略适用于哪个客户端以及何时适用。某些条件在客户端创建/更新时检查,而其他条件在客户端请求期间检查(OIDC 授权请求、令牌端点请求等)。条件检查是否满足指定的标准。例如,某些条件检查客户端的访问类型是否为保密。

条件不能单独使用。它可以在之后描述的 策略 中使用。

条件可以像其他可配置的提供程序一样配置。可以配置什么取决于每个条件的性质。

提供了以下条件

创建/更新客户端的方式
  • 动态客户端注册(匿名或通过初始访问令牌或注册访问令牌进行身份验证)

  • 管理 REST API(管理控制台等)

例如,在创建客户端时,可以将条件配置为当此客户端由没有初始访问令牌的 OIDC 动态客户端注册(匿名动态客户端注册)创建时评估为 true。因此,此条件可以用于例如确保通过 OIDC 动态客户端注册注册的所有客户端都符合 FAPI 或 OAuth 2.1。

客户端的作者(通过是否存在于特定角色或组来检查)

在 OpenID Connect 动态客户端注册中,客户端的作者是经过身份验证以获取访问令牌以生成新客户端的最终用户,而不是实际使用访问令牌访问注册端点的现有客户端的服务帐户。通过管理 REST API 进行注册时,客户端的作者是最终用户,例如 Keycloak 的管理员。

客户端访问类型(保密、公开、仅持有者)

例如,当客户端发送授权请求时,如果此客户端是保密的,则采用策略。保密客户端在启用客户端身份验证时,公开客户端禁用客户端身份验证。仅持有者是一种已弃用的客户端类型。

客户端作用域

如果客户端具有特定的客户端作用域(作为默认作用域或当前请求中使用的可选作用域),则评估为 true。例如,这可以用于确保具有作用域 fapi-example-scope 的 OIDC 授权请求需要符合 FAPI。

客户端角色

适用于具有指定名称的客户端角色的客户端。通常,您可以为请求的客户端创建指定名称的客户端角色,并将其用作“标记角色”,以确保指定的客户端策略将应用于请求的客户端。

经常存在对特定客户端(例如 my-client-1my-client-2)应用特定客户端策略的用例。实现此结果的最佳方法是在您的策略中使用 客户端角色 条件,然后为请求的客户端创建指定名称的客户端角色。此客户端角色可以用作“标记角色”,仅用于标记特定客户端的特定客户端策略。
客户端域名、主机名或 IP 地址

应用于客户端的特定域名。或用于管理员从特定主机名或 IP 地址注册/更新客户端的情况。

客户端属性

应用于具有指定名称和值的客户端属性的客户端。如果指定多个客户端属性,它们将使用 AND 条件进行评估。如果想要使用 OR 条件进行评估,请多次设置此条件。

任何客户端

此条件始终评估为 true。例如,它可以用于确保特定 realm 中的所有客户端都符合 FAPI。

ACR 条件

当身份验证请求中请求的 ACR 值与条件中配置的值匹配时应用。例如,它可以用于根据请求的 ACR 值选择身份验证流程。有关更多详细信息,请参阅相关文档官方 OIDC 规范

授权类型

当使用特定的授权类型时,评估结果为 true。例如,它可以与客户端 Scope 结合使用,以在请求特定客户端 Scope 时阻止令牌交换请求。

执行器

执行器指定对采用策略的客户端执行的操作。执行器执行一个或多个指定的操作。例如,某些执行器检查授权请求中参数 redirect_uri 的值是否与授权端点上预先注册的重定向 URI 之一完全匹配,如果不匹配则拒绝此请求。

执行器不能单独使用。它可以在之后描述的配置文件中使用。

执行器可以像其他可配置的提供程序一样进行配置。可以配置的内容取决于每个执行器的性质。

执行器对各种事件起作用。执行器实现可以忽略某些类型的事件(例如,用于检查 OIDC request 对象的执行器仅对 OIDC 授权请求起作用)。事件包括

  • 创建客户端(包括通过动态客户端注册创建)

  • 更新客户端

  • 发送授权请求

  • 发送令牌请求

  • 发送令牌刷新请求

  • 发送令牌撤销请求

  • 发送令牌自省请求

  • 发送 userinfo 请求

  • 发送带有刷新令牌的注销请求(请注意,使用刷新令牌注销是 Keycloak 专有的功能,任何规范都不支持。建议依赖官方 OIDC 注销)。

在每个事件中,执行器可以在多个阶段工作。例如,在创建/更新客户端时,执行器可以通过自动配置特定的客户端设置来修改客户端配置。之后,执行器在验证阶段验证此配置。

此执行器的几个目的之一是实现客户端一致性配置文件(如 FAPI 和 OAuth 2.1)的安全要求。为此,需要以下执行器

  • 强制客户端使用安全的 客户端身份验证方法

  • 强制使用 持有者密钥令牌

  • 强制使用 代码交换证明密钥 (PKCE)

  • 强制对 签名 JWT 客户端身份验证(private-key-jwt)使用安全的签名算法

  • 强制 HTTPS 重定向 URI,并确保配置的重定向 URI 不包含通配符

  • 强制 OIDC request 对象满足高安全级别

  • 强制 OIDC 混合流程的响应类型,包括用作分离签名的 ID 令牌,如 FAPI 1 规范中所述,这意味着从授权响应返回的 ID 令牌将不包含用户个人资料数据

  • 强制更安全的 statenonce 参数处理,以防止 CSRF

  • 强制客户端注册时使用更安全的签名算法

  • 强制 CIBA 请求使用 binding_message 参数

  • 强制 客户端密钥轮换

  • 强制客户端注册访问令牌

  • 强制检查客户端是否是在使用意图的用例中发出意图的客户端,例如在启动授权码流程以获取访问令牌之前发出意图的 UK OpenBanking

  • 强制禁止隐式和混合流程

  • 强制检查 PAR 请求是否包含授权请求包含的必要参数

  • 强制使用 DPoP 绑定令牌(当启用 dpop 功能时可用)

  • 强制使用轻量级访问令牌

  • 强制跳过刷新令牌轮换,并且刷新令牌响应中不返回刷新令牌

  • 强制 OAuth 2.1 规范要求的有效重定向 URI

  • 强制不能使用 SAML 重定向绑定,或者 SAML 请求和断言已签名

另一个可用的执行器是 auth-flow-enforce,它可以用于在身份验证请求期间强制执行身份验证流程。例如,它可以用于根据某些条件(例如特定的 scope 或 ACR 值)选择流程。有关更多详细信息,请参阅相关文档

配置文件

配置文件由多个执行器组成,可以实现 FAPI 和 OAuth 2.1 等安全配置文件。配置文件可以通过 Admin REST API(Admin Console)及其执行器一起配置。存在三个全局配置文件,它们在 Keycloak 中默认配置,并预配置了符合 FAPI 1 Baseline、FAPI 1 Advanced、FAPI CIBA、FAPI 2 和 OAuth 2.1 规范的执行器。更多详细信息请参阅保护应用程序部分中的 FAPIOAuth 2.1

策略

策略由多个条件和配置文件组成。该策略可以应用于满足此策略所有条件的客户端。策略引用多个配置文件,并且这些配置文件的所有执行器都对采用该策略的客户端执行其任务。

配置

策略、配置文件、条件、执行器可以通过 Admin REST API 进行配置,这也意味着可以通过 Admin Console 进行配置。为此,有一个选项卡 RealmRealm SettingsClient Policies,这意味着管理员可以为每个 realm 设置客户端策略。

全局客户端配置文件在每个 realm 中自动可用。但是,默认情况下未配置任何客户端策略。这意味着,如果管理员希望其 realm 的客户端符合 FAPI 标准,则始终需要创建任何客户端策略。全局配置文件无法更新,但管理员可以轻松地将它们用作模板,并在想要对全局配置文件配置进行一些细微更改时创建自己的配置文件。Admin Console 中提供了 JSON 编辑器,这简化了基于某些全局配置文件创建新配置文件的过程。

向后兼容性

客户端策略可以替换 保护应用程序指南客户端注册服务中描述的客户端注册策略。但是,客户端注册策略仍然共存。这意味着,例如,在动态客户端注册请求以创建/更新客户端期间,客户端策略和客户端注册策略都会被应用。

目前的计划是删除客户端注册策略功能,现有的客户端注册策略将自动迁移到新的客户端策略中。

客户端密钥轮换示例

请参阅客户端密钥轮换的示例配置。

将 Keycloak 配置为可验证凭证颁发者

这是一个实验性功能,不应在生产环境中使用。不保证向后兼容性,并且未来的更新可能会引入破坏性更改。

Keycloak 为 OpenID for Verifiable Credential Issuance 提供实验性支持。

简介

本章提供将 Keycloak 配置为使用 OpenID for Verifiable Credential Issuance (OID4VCI) 协议的可验证凭证颁发者的分步说明。它概述了设置 Keycloak 实例以安全地颁发和管理可验证凭证 (VC) 的过程,从而支持去中心化身份解决方案。

什么是可验证凭证 (VC)?

可验证凭证 (VC) 是加密签名的、防篡改的数据结构,表示关于实体(例如个人、组织或设备)的声明。它们是去中心化身份系统的基础,允许安全且保护隐私的身份验证,而无需依赖中心化机构。VC 支持选择性披露和零知识证明等高级功能,从而增强用户隐私和安全性。

什么是 OID4VCI?

OpenID for Verifiable Credential Issuance (OID4VCI) 是 OpenID Connect (OIDC) 协议的扩展。它定义了一个标准化的、可互操作的框架,供凭证颁发者向持有者交付 VC,然后持有者可以将它们呈现给验证者。OID4VCI 利用 Keycloak 现有的身份验证和授权功能来简化 VC 颁发。

本章范围

本章涵盖以下技术配置

  • 为 VC 颁发创建专用 realm。

  • 设置测试用户以进行凭证测试。

  • 配置自定义加密密钥以用于签名和加密 VC。

  • 定义 realm 属性以指定 VC 元数据。

  • 建立客户端 scope 和映射器,以在 VC 中包含用户属性。

  • 注册客户端以处理 VC 请求。

  • 配置凭证构建器以进行 VC 格式化。

  • 使用颁发者元数据端点验证配置。

先决条件

在将 Keycloak 配置为可验证凭证颁发者之前,请确保满足以下要求

Keycloak 实例

运行中的 Keycloak 服务器,并已启用 OID4VCI 功能。

要启用该功能,请将以下标志添加到启动命令

--features=oid4vc-vci

通过检查服务器日志中是否有 OID4VC_VCI 初始化消息来验证激活。

身份验证

需要访问令牌才能验证 API 请求。

有关详细步骤,请参阅以下 Keycloak 文档部分

配置步骤

请按照以下步骤将 Keycloak 配置为可验证凭证颁发者。每个部分都详细介绍了程序、解释和示例(如果适用)。

创建 Realm

Keycloak 中的 realm 是一个逻辑容器,用于管理用户、客户端、角色和身份验证流程。对于可验证凭证 (VC) 颁发,请创建一个专用 realm 以确保隔离并保持功能的清晰分离。

有关创建 realm 的详细说明,请参阅 Keycloak 文档:创建 Realm

创建用户帐户

需要一个测试用户来模拟凭证颁发并验证设置。

有关创建用户的分步说明,请参阅 Keycloak 文档:创建用户

确保用户具有有效的用户名、电子邮件和密码。如果首次登录时不应重置密码,请在密码配置期间禁用“临时”切换。

密钥管理配置

Keycloak 使用加密密钥来签名和加密可验证凭证 (VC)。为了确保安全且符合标准的颁发,请使用密钥库配置 ECDSA (ES256) 用于签名RSA (RS256) 用于签名RSA-OAEP 用于加密

有关配置 realm 密钥的详细指南,请参阅 Keycloak 文档:管理 Realm 密钥

配置密钥提供程序

要为 VC 颁发启用加密操作

  • ECDSA (ES256) 密钥:用于使用 ES256 算法对 VC 进行签名。

  • RSA (RS256) 密钥:使用 RS256 的备用签名机制。

  • RSA-OAEP 密钥:用于加密 VC 中的敏感数据。

每个密钥都必须注册为 Realm 设置 > 密钥 部分中的 java-keystore 提供程序,确保: - 密钥库文件已正确指定并安全存储。 - 已选择适当的算法(ES256、RS256 或 RSA-OAEP)。 - 密钥处于活动状态、已启用,并配置了正确的使用方式(签名或加密)。 - 已设置优先级值以定义密钥之间的优先级。

确保密钥库文件安全存储并且 Keycloak 服务器可以访问。使用强密码来保护密钥库和私钥。

注册 Realm 属性

Realm 属性定义可验证凭证 (VC) 的元数据,例如过期时间、支持的格式和 scope 定义。这些属性允许 Keycloak 使用预定义设置颁发 VC。

由于 Keycloak Admin Console 不支持直接属性创建,请使用 Keycloak Admin REST API 来配置这些属性。

定义 Realm 属性

创建一个 JSON 文件(例如,realm-attributes.json),其中包含以下内容

{
  "realm": "oid4vc-vci",
  "enabled": true,
  "preAuthorizedCodeLifespanS": 120,
  "issuerDid": "https://#:8443/realms/oid4vc-vci",
  "attributes": {
    "vc.IdentityCredential.expiry_in_s": "31536000",
    "vc.IdentityCredential.format": "vc+sd-jwt",
    "vc.IdentityCredential.scope": "identity_credential",
    "vc.IdentityCredential.vct": "https://credentials.example.com/identity_credential",
    "vc.SteuerberaterCredential.expiry_in_s": "31536000",
    "vc.SteuerberaterCredential.format": "vc+sd-jwt",
    "vc.SteuerberaterCredential.scope": "stbk_westfalen_lippe",
    "vc.SteuerberaterCredential.vct": "stbk_westfalen_lippe",
    "vc.SteuerberaterCredential.cryptographic_binding_methods_supported": "jwk"
  }
}

这是一个示例配置。您可以根据您的特定需求定义其他属性,例如: - 不同的 VC 类型和 scope。 - 备用凭证格式。 - 自定义加密设置。

属性分解

  • preAuthorizedCodeLifespanS – 定义预授权代码保持有效的时间(以秒为单位)。

  • issuerDid – 颁发者的去中心化标识符 (DID)。

  • attributes – 包含 VC 特定的元数据,可以根据需要进行扩展

  • expiry_in_s – 凭证过期时间(以秒为单位)。

  • format – 定义 VC 格式(例如,vc+sd-jwt)。

  • scope – 标识凭证的 scope。

  • vct可验证凭证类型 (VCT)

  • cryptographic_binding_methods_supported – 指定支持的加密方法(如果适用)。

导入 Realm 属性

使用以下 curl 命令将属性导入到 Keycloak

curl -X POST "https://#:8443/admin/realms/oid4vc-vci" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @realm-attributes.json
  • $ACCESS_TOKEN 替换为有效的 Keycloak Admin API 访问令牌

  • 避免在生产环境中使用 -k;而是配置 受信任的 TLS 证书

  • 如果更新现有 realm,请使用 PUT 而不是 POST

创建带有映射器的客户端 Scope

客户端 scope 定义了 哪些用户属性 包含在可验证凭证 (VC) 中。这些 scope 使用协议映射器将特定的声明映射到 VC 中。

由于 Keycloak 管理控制台不支持直接创建带有映射器的客户端作用域,请使用 Keycloak 管理 REST API

定义带有映射器的客户端作用域

创建一个 JSON 文件(例如,client-scopes.json),内容如下:

{
  "name": "vc-scope-mapping",
  "protocol": "openid-connect",
  "attributes": {
    "include.in.token.scope": "false",
    "display.on.consent.screen": "false"
  },
  "protocolMappers": [
    {
      "name": "academic_title-mapper-bsk",
      "protocol": "oid4vc",
      "protocolMapper": "oid4vc-static-claim-mapper",
      "config": {
        "subjectProperty": "academic_title",
        "staticValue": "N/A",
        "supportedCredentialTypes": "stbk_westfalen_lippe"
      }
    }
  ]
}

这是一个示例配置。您可以定义额外的协议映射器来支持不同的声明映射,例如: - 动态属性值而不是静态属性值。 - 每个凭证类型映射多个属性。 - 替代的支持凭证类型。

属性细分

  • name – 客户端作用域的名称。

  • protocol – 对于标准的 OAuth2 工作流程,使用 openid-connect

  • attributes – 定义作用域可见性和用户同意行为

  • include.in.token.scope: 此作用域是否应包含在访问令牌中。

  • display.on.consent.screen: 是否在用户同意屏幕上显示此作用域。

  • protocolMappers – 定义如何映射声明

  • name – 映射器标识符。

  • protocol – 对于可验证凭据,使用 oid4vc

  • protocolMapper – 指定声明映射策略(例如,oid4vc-static-claim-mapper)。

  • config:

  • subjectProperty – 要映射的用户属性。

  • staticValue – 当属性缺失时分配的静态值。

  • supportedCredentialTypes – 支持此声明的凭证类型。

导入客户端作用域

使用以下 curl 命令将客户端作用域导入到 Keycloak 中

curl -X POST "https://#:8443/admin/realms/oid4vc-vci/client-scopes" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @client-scopes.json
  • $ACCESS_TOKEN 替换为有效的 Keycloak Admin API 访问令牌

  • 避免在生产环境中使用 -k;而是配置 受信任的 TLS 证书

  • 如果更新现有作用域,请使用 PUT 代替 POST

创建 OID4VC 客户端

设置一个客户端来处理 VC 请求,并为其分配必要的作用域。

  1. 创建一个 JSON 文件(例如,oid4vc-rest-api-client.json),内容如下:

    {
      "clientId": "oid4vc-rest-api",
      "enabled": true,
      "protocol": "openid-connect",
      "publicClient": false,
      "serviceAccountsEnabled": true,
      "clientAuthenticatorType": "client-secret",
      "redirectUris": ["https://#:8080/*"],
      "directAccessGrantsEnabled": true,
      "defaultClientScopes": ["profile"],
      "optionalClientScopes": ["vc-scope-mapping"],
      "attributes": {
        "client.secret.creation.time": "1719785014",
        "client.introspection.response.allow.jwt.claim.enabled": "false",
        "login_theme": "keycloak",
        "post.logout.redirect.uris": "https://#:8080"
      }
    }
    • clientId: 客户端的唯一标识符。

    • optionalClientScopes: 链接用于 VC 请求的 vc-scope-mapping 作用域。

  2. 使用以下 curl 命令导入客户端

    curl -k -X POST "https://#:8443/admin/realms/oid4vc-vci/clients" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d @oid4vc-rest-api-client.json

创建凭据构建器组件

凭据构建器负责格式化可验证凭据 (VC),例如 SD-JWT。此组件必须使用 Admin REST API 在 Keycloak 中注册

注册凭据构建器

使用以下 curl 命令来创建凭据构建器

curl -X POST "https://#:8443/admin/realms/oid4vc-vci/components" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "sd-jwt-credentialbuilder",
    "providerId": "vc+sd-jwt",
    "providerType": "org.keycloak.protocol.oid4vc.issuance.credentialbuilder.CredentialBuilder"
  }'
  • $ACCESS_TOKEN 替换为有效的 Keycloak Admin API 访问令牌

  • 避免在生产环境中使用 -k;而是配置 受信任的 TLS 证书

配置详情

  • name – 凭据构建器的标识符。

  • providerId – 指定 VC 格式(例如,vc+sd-jwt)。

  • providerType – 指向用于 VC 颁发的 Keycloak 凭据构建器类

这是一个示例配置。您可以为不同的 VC 格式(例如,JWT、JSON-LD 等)注册多个凭据构建器

验证配置

通过访问颁发者元数据端点来验证设置

  1. 打开浏览器或使用 curl 等工具访问

    https://#:8443/realms/oid4vc-vci/.well-known/openid-credential-issuer

成功的响应会返回一个 JSON 对象,其中包含如下详细信息: - 支持的声明 - 凭据格式 - 颁发者元数据

结论

您已使用 OID4VCI 协议成功配置 Keycloak 作为可验证凭据颁发者。此设置利用 Keycloak 强大的身份管理能力来颁发安全的、符合标准的 VC

有关完整的参考实现,请参阅示例项目: Keycloak SSI Deployment

使用 Vault 获取密钥

Keycloak 目前提供了 Vault SPI 的两个开箱即用实现:基于纯文本文件的 Vault 和基于 Java KeyStore 的 Vault。

要从 Vault 获取密钥而不是直接输入,请在相应的字段中输入以下特殊构造的字符串

${vault.key}

其中 key 是 Vault 识别的密钥名称。

为了防止密钥跨 realm 泄漏,Keycloak 将 realm 名称与从 Vault 表达式中获取的 key 组合在一起。这种方法意味着 key 不直接映射到 Vault 中的条目,而是根据用于将 key 与 realm 名称组合的算法创建最终的条目名称。对于基于文件的 Vault,这种组合反映为一个特定的文件名,对于基于 Java KeyStore 的 Vault,它是一个特定的别名。

您可以从以下字段中的 Vault 获取密钥

SMTP 密码

在 realm 的 SMTP 设置

LDAP 绑定凭据

在基于 LDAP 的用户联合的 LDAP 设置中。

OIDC 身份提供商密钥

在身份提供商 OpenID Connect 配置中的客户端密钥

密钥解析器

所有内置提供程序都支持密钥解析器的配置。密钥解析器实现了将 realm 名称与从 ${vault.key} 表达式中获取的密钥组合成最终条目名称的算法或策略,该最终条目名称用于从 Vault 中检索密钥。Keycloak 使用 keyResolvers 属性来配置提供程序使用的解析器。该值是以逗号分隔的解析器名称列表。以下是 files-plaintext 提供程序的配置示例

kc.[sh|bat] start --spi-vault-file-key-resolvers=REALM_UNDERSCORE_KEY,KEY_ONLY

解析器按照您在配置中声明的顺序运行。对于每个解析器,Keycloak 使用解析器生成的最后一个条目名称,该名称将 realm 与 Vault 密钥组合在一起以搜索 Vault 的密钥。如果 Keycloak 找到密钥,则返回该密钥。否则,Keycloak 使用下一个解析器再次搜索。此搜索将继续进行,直到 Keycloak 找到非空密钥或用完解析器为止。如果 Keycloak 找不到密钥,则 Keycloak 返回空密钥。

在前面的示例中,Keycloak 首先使用 REALM_UNDERSCORE_KEY 解析器。如果 Keycloak 使用该解析器在 Vault 中找到条目,则 Keycloak 返回该条目。否则,Keycloak 使用 KEY_ONLY 解析器再次搜索。如果 Keycloak 通过使用 KEY_ONLY 解析器找到条目,则 Keycloak 返回该条目。如果 Keycloak 使用了所有解析器,则 Keycloak 返回一个空密钥。

以下是当前可用解析器的列表

名称 描述

KEY_ONLY

Keycloak 忽略 realm 名称,并使用 Vault 表达式中的密钥。Keycloak 使用另一个下划线字符转义密钥中出现的下划线。例如,如果密钥名为 my_secret,则 Keycloak 在 Vault 中搜索名为 my__secret 的条目。这是为了防止与默认的 REALM_UNDERSCORE_KEY 解析器发生冲突。

REALM_UNDERSCORE_KEY

Keycloak 通过使用下划线字符组合 realm 和密钥。Keycloak 使用另一个下划线字符转义 realm 或密钥中出现的下划线。例如,如果 realm 名为 master_realm,密钥为 smtp_key,则组合后的密钥为 master__realm_smtp__key

REALM_FILESEPARATOR_KEY

Keycloak 通过使用平台文件分隔符字符组合 realm 和密钥。Vault 表达式禁止使用可能导致路径遍历的字符,从而防止访问相应 realm 之外的密钥。

FACTORY_PROVIDED

Keycloak 通过使用 Vault 提供程序工厂的 VaultKeyResolver 组合 realm 和密钥,从而允许通过扩展现有工厂并实现 getFactoryResolver 方法来创建自定义密钥解析器。

如果您没有为内置提供程序配置解析器,则 Keycloak 将选择 REALM_UNDERSCORE_KEY

配置审计以跟踪事件

Keycloak 包含一套审计功能。您可以记录每个登录和管理员操作,并在管理控制台中查看这些操作。Keycloak 还包含一个监听器 SPI,用于监听事件并可以触发操作。内置监听器的示例包括日志文件和在事件发生时发送电子邮件。

审计用户事件

您可以记录和查看每个影响用户的事件。Keycloak 会为诸如用户成功登录、用户输入错误密码或用户帐户更新之类的操作触发登录事件。默认情况下,Keycloak 不会在管理控制台中存储或显示事件。只有错误事件才会记录到管理控制台和服务器的日志文件中。

步骤

使用此过程开始审计用户事件。

  1. 在菜单中单击“Realm 设置”。

  2. 单击事件选项卡。

  3. 单击用户事件设置选项卡。

  4. 保存事件切换为开启

    用户事件设置

    User events settings

  5. 过期时间字段中指定存储事件的时长。

  6. 单击添加已保存类型以查看您可以保存的其他事件。

    添加类型

    Add types

  7. 点击 添加

当您要删除所有已保存的事件时,单击清除用户事件

步骤

您现在可以查看事件了。

  1. 单击菜单中的事件选项卡。

    用户事件

    Login Events

  2. 要过滤事件,请单击搜索用户事件

    搜索用户事件

    Search user event

事件类型

登录事件

事件 描述

登录

用户登录。

注册

用户注册。

注销

用户注销。

代码到令牌

应用程序或客户端将代码交换为令牌。

刷新令牌

应用程序或客户端刷新令牌。

暴力破解保护

事件 描述

用户因永久锁定而被禁用

由于登录失败次数过多,暴力破解保护永久禁用了用户帐户。

用户因临时锁定而被禁用

由于登录失败次数过多,暴力破解保护临时禁用了用户帐户。

身份代理

事件 描述

联合身份链接覆盖

现有的联合身份链接被覆盖

联合身份链接覆盖错误

尝试覆盖现有联合身份链接时发生错误

OAuth

事件 描述

OAuth2 扩展授权

OAuth2 授权已执行

OAuth2 扩展授权错误

OAuth2 授权执行期间发生错误

帐户事件

事件 描述

社交链接

用户帐户链接到社交媒体提供商。

移除社交链接

从社交媒体帐户到用户帐户的链接断开。

更新电子邮件

帐户的电子邮件地址已更改。

更新个人资料

帐户的个人资料已更改。

发送密码重置

Keycloak 发送密码重置电子邮件。

更新密码(已弃用)

帐户的密码已更改。

更新凭据

帐户的密码或(基于时间的)一次性密码 (OTP/TOTP) 设置已更改。

更新 TOTP(已弃用)

帐户的基于时间的一次性密码 (TOTP) 设置已更改。

移除 TOTP(已弃用)

Keycloak 从帐户中移除 TOTP。

移除凭据

Keycloak 从帐户中移除凭据。

发送验证电子邮件

Keycloak 发送电子邮件验证电子邮件。

验证电子邮件

Keycloak 验证帐户的电子邮件地址。

每个事件都有一个相应的错误事件。

事件监听器

事件监听器监听事件并根据该事件执行操作。Keycloak 包括两个内置监听器:日志记录事件监听器和电子邮件事件监听器。

日志记录事件监听器

启用日志记录事件监听器后,当发生错误事件时,此监听器会写入日志文件。

来自日志记录事件监听器的示例日志消息

11:36:09,965 WARN  [org.keycloak.events] (default task-51) type=LOGIN_ERROR, realmId=master,
                    clientId=myapp,
                    userId=19aeb848-96fc-44f6-b0a3-59a17570d374, ipAddress=127.0.0.1,
                    error=invalid_user_credentials, auth_method=openid-connect, auth_type=code,
                    redirect_uri=https://#:8180/myapp,
                    code_id=b669da14-cdbb-41d0-b055-0810a0334607, username=admin

您可以使用日志记录事件监听器来防御黑客机器人攻击

  1. 解析日志文件以查找 LOGIN_ERROR 事件。

  2. 提取失败登录事件的 IP 地址。

  3. 将 IP 地址发送到入侵防御软件框架工具。

日志记录事件监听器将事件记录到 org.keycloak.events 日志类别。默认情况下,Keycloak 不会在服务器日志中包含调试日志事件。

要在服务器日志中包含调试日志事件

  1. 更改 org.keycloak.events 类别的日志级别

  2. 更改日志记录事件监听器使用的日志级别。

要更改日志记录事件监听器使用的日志级别,请添加以下内容

bin/kc.[sh|bat] start --spi-events-listener-jboss-logging-success-level=info --spi-events-listener-jboss-logging-error-level=error

日志级别的有效值为 debuginfowarnerrorfatal

电子邮件事件监听器

当事件发生时,电子邮件事件监听器会向用户的电子邮件地址发送消息,并支持以下事件

  • 登录错误。

  • 更新密码。

  • 更新基于时间的一次性密码 (TOTP)。

  • 移除一次性密码 (OTP)。

  • 更新凭据。

  • 移除凭据。

以下是可以配置的可选事件

  • 用户因永久锁定而被禁用。

  • 用户因临时锁定而被禁用。

要发送电子邮件,需要满足以下条件

  • 用户拥有电子邮件地址。

  • 用户的电子邮件地址被标记为已验证。

先决条件
  • realm 的电子邮件设置已配置。

步骤

要启用电子邮件监听器

  1. 在菜单中单击“Realm 设置”。

  2. 单击事件选项卡。

  3. 单击事件监听器字段。

  4. 选择 email

    事件监听器

    Event listeners

您可以使用 --spi-events-listener-email-exclude-events 参数排除事件。例如

kc.[sh|bat] --spi-events-listener-email-exclude-events=UPDATE_CREDENTIAL,REMOVE_CREDENTIAL

要启用可选事件,请使用以下命令

kc.[sh|bat] --spi-events-listener-email-include-events=USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR,USER_DISABLED_BY_PERMANENT_LOCKOUT

审计管理员事件

您可以记录管理员在管理控制台中执行的所有操作。管理控制台通过调用 Keycloak REST 接口执行管理操作,而 Keycloak 会审计这些 REST 调用。您可以在管理控制台中查看生成的事件。

步骤

使用此步骤开始审计管理员操作。

  1. 在菜单中单击“Realm 设置”。

  2. 单击事件选项卡。

  3. 点击 管理事件设置 选项卡。

  4. 保存事件切换为开启

    Keycloak 显示 包含表示 开关。

  5. 包含表示 切换到 开启

    包含表示 开关包含通过管理 REST API 发送的 JSON 文档,以便您可以查看管理员的操作。

    管理事件设置

    Admin events settings

  6. 点击 保存

  7. 要清除数据库中存储的操作,请单击 清除管理事件

步骤

您现在可以查看管理事件。

  1. 点击菜单中的 事件

  2. 点击 管理事件 选项卡。

    管理事件

    Admin events

包含表示 开关处于开启状态时,可能会导致在数据库中存储大量信息。您可以使用 --spi-events-store-jpa-max-field-length 参数设置表示的最大长度。如果您想遵守底层存储限制,此设置非常有用。例如

kc.[sh|bat] --spi-events-store-jpa-max-field-length=2500

缓解安全威胁

任何身份验证服务器都存在安全漏洞。 有关更多信息,请参阅互联网工程任务组 (IETF) 的 OAuth 2.0 威胁模型OAuth 2.0 安全最佳当前实践

主机

Keycloak 在多种方式中使用公共主机名,例如在令牌颁发者字段和密码重置电子邮件中的 URL 中。

默认情况下,主机名源自请求标头。 没有验证来确保主机名有效。 如果您没有将负载均衡器或代理与 Keycloak 一起使用以防止无效的主机头,请配置可接受的主机名。

主机名的服务提供程序接口 (SPI) 提供了一种为请求配置主机名的方法。 您可以使用此内置提供程序为前端请求设置固定 URL,同时允许基于请求 URI 的后端请求。 如果内置提供程序没有所需的功能,您可以开发自定义提供程序。

管理端点和管理控制台

Keycloak 在与非管理用途相同的端口上公开管理 REST API 和 Web 控制台。 如果不需要外部访问,请勿在外部公开管理端点。

暴力攻击

暴力攻击试图通过多次尝试登录来猜测用户的密码。 Keycloak 具有暴力检测功能,如果登录失败次数超过指定阈值,它可以永久或暂时禁用用户帐户。

当用户被锁定并尝试登录时,Keycloak 会显示默认的 用户名或密码无效 错误消息。 此消息与无效用户名或无效密码显示的消息相同,以确保攻击者不知道该帐户已被禁用。

暴力检测默认情况下处于禁用状态。 启用此功能以防止暴力攻击。

要启用此保护

  1. 点击菜单中的 领域设置

  2. 单击 安全防御 选项卡。

  3. 点击 暴力检测 选项卡。

  4. 选择最适合您需求的 暴力模式

    暴力检测

    brute force

永久锁定

Keycloak 禁用用户帐户(阻止登录尝试),直到管理员重新启用它。

永久锁定

brute force permanently

永久锁定参数

名称 描述 默认

最大登录失败次数

最大登录失败次数。

30 次失败

快速登录检查毫秒数

登录尝试之间的最短时间。

1000 毫秒

最短快速登录等待时间

当登录尝试快于快速登录检查毫秒数时,用户被禁用的最短时间。

1 分钟

永久锁定流程

  1. 成功登录时

    1. 重置 count

  2. 登录失败时

    1. 增加 count

    2. 如果 count 大于或等于 最大登录失败次数

      1. 锁定用户

    3. 否则,如果本次失败与上次失败之间的时间小于快速登录检查毫秒数

      1. 将用户锁定 最短快速登录等待时间 指定的时间

启用用户帐户会重置 count

临时锁定

Keycloak 会在特定时间段内禁用用户帐户。 随着攻击的持续,帐户被禁用的时间段会增加。

临时锁定

brute force temporarily

临时锁定参数

名称 描述 默认

最大登录失败次数

最大登录失败次数。

30 次失败

增加等待时间的策略

当用户的登录尝试次数超过最大登录失败次数时,增加用户被临时禁用的时间的策略

倍数

等待时间增量

当用户的登录尝试次数超过最大登录失败次数时,添加到用户被临时禁用的时间的时间。

1 分钟

最大等待时间

用户被临时禁用的最长时间。

15 分钟

失败重置时间

失败计数重置的时间。 计时器从上次登录失败开始运行。 确保此数字始终大于 最大等待时间;否则,有效等待时间将永远不会达到您设置为 最大等待时间 的值。

12 小时

快速登录检查毫秒数

登录尝试之间的最短时间。

1000 毫秒

最短快速登录等待时间

当登录尝试快于快速登录检查毫秒数时,用户被禁用的最短时间。

1 分钟

临时锁定算法

  1. 成功登录时

    1. 重置 count

  2. 登录失败时

    1. 如果本次失败与上次失败之间的时间大于失败重置时间

      1. 重置 count

    2. 增加 count

    3. 根据定义的暴力破解策略计算 wait(请参阅下面的设置等待时间策略)。

    4. 如果 wait 小于或等于 0 并且本次失败与上次失败之间的时间小于快速登录检查毫秒数

      1. wait 设置为 最短快速登录等待时间

    5. 如果 wait 大于 0

      1. 将用户临时禁用 wait最大等待时间 秒中的较小值

当临时禁用的帐户提交登录失败时,count 不会增加。

设置等待时间的策略

Keycloak 提供了两种策略来计算等待时间:倍数或线性。 倍数策略是 Keycloak 最先引入的策略,因此是默认策略。

按倍数策略,当失败次数(或计数)是 最大登录失败次数 的倍数时,等待时间会增加。 例如,如果您将 最大登录失败次数 设置为 5,并将 等待时间增量 设置为 30 秒,则在多次身份验证尝试失败后,帐户被禁用的有效时间将为

失败次数

等待时间增量

最大登录失败次数

有效等待时间

1

30

5

0

2

30

5

0

3

30

5

0

4

30

5

0

5

30

5

30

6

30

5

30

7

30

5

30

8

30

5

30

9

30

5

30

10

30

5

60

在第五次尝试失败时,帐户将被禁用 30 秒。 在达到 最大登录失败次数 的下一个倍数(在本例中为 10)后,时间从 30 秒增加到 60 秒。

按倍数策略使用以下公式计算等待时间:等待时间增量(秒) * (count / 最大登录失败次数)。 除法是向下舍入为整数的整数除法。

对于线性策略,当失败的 count(或次数)大于或等于 最大登录失败次数 时,等待时间会增加。 例如,如果您将 最大登录失败次数 设置为 5,并将 等待时间增量 设置为 30 秒,则在多次身份验证尝试失败后,帐户被禁用的有效时间将为

失败次数

等待时间增量

最大登录失败次数

有效等待时间

1

30

5

0

2

30

5

0

3

30

5

0

4

30

5

0

5

30

5

30

6

30

5

60

7

30

5

90

8

30

5

120

9

30

5

150

10

30

5

180

在第五次尝试失败时,帐户将被禁用 30 秒。 每次新的失败都会根据 等待时间增量 中指定的值增加等待时间。

线性策略使用以下公式计算等待时间:等待时间增量(秒) * (1 + count - 最大登录失败次数)。

临时锁定后永久锁定

混合模式。 将用户临时锁定指定次数,然后永久锁定用户。

临时锁定后永久锁定

brute force mixed

临时锁定后永久锁定参数

名称 描述 默认

最大登录失败次数

最大登录失败次数。

30 次失败

最大临时锁定次数

在发生永久锁定之前允许的最大临时锁定次数。

1

增加等待时间的策略

当用户的登录尝试次数超过最大登录失败次数时,增加用户被临时禁用的时间的策略

倍数

等待时间增量

当用户的登录尝试次数超过最大登录失败次数时,添加到用户被临时禁用的时间的时间。

1 分钟

最大等待时间

用户被临时禁用的最长时间。

15 分钟

失败重置时间

失败计数重置的时间。 计时器从上次登录失败开始运行。 确保此数字始终大于 最大等待时间;否则,有效等待时间将永远不会达到您设置为 最大等待时间 的值。

12 小时

快速登录检查毫秒数

登录尝试之间的最短时间。

1000 毫秒

最短快速登录等待时间

当登录尝试快于快速登录检查毫秒数时,用户被禁用的最短时间。

1 分钟

临时锁定后永久锁定算法

  1. 成功登录时

    1. 重置 count

    2. 重置 temporary lockout 计数器

  2. 登录失败时

    1. 如果本次失败与上次失败之间的时间大于失败重置时间

      1. 重置 count

      2. 重置 temporary lockout 计数器

    2. 增加 count

    3. 根据定义的暴力破解策略计算 wait(请参阅下面的设置等待时间策略)。

    4. 如果 wait 小于或等于 0 并且本次失败与上次失败之间的时间小于快速登录检查毫秒数

      1. wait 设置为 最短快速登录等待时间

      2. quick login failure 设置为 true

    5. 如果 wait最大临时锁定次数 大于 0

      1. wait 设置为 wait最大等待时间 秒中的较小值

    6. 如果 quick login failurefalse

      1. 增加 temporary lockout 计数器

    7. 如果 temporary lockout 计数器超过 最大临时锁定次数

      1. 永久锁定用户

    8. 否则

      1. 根据 wait 值临时阻止用户

当临时禁用的帐户提交登录失败时,count 不会增加。

Keycloak 暴力检测的缺点

Keycloak 暴力检测的缺点是服务器容易受到拒绝服务攻击。 在实施拒绝服务攻击时,攻击者可以尝试通过猜测其知道的任何帐户的密码来登录,并最终导致 Keycloak 禁用这些帐户。

考虑使用入侵防御软件 (IPS)。 Keycloak 记录每次登录失败和客户端 IP 地址失败。 您可以将 IPS 指向 Keycloak 服务器的日志文件,并且 IPS 可以修改防火墙以阻止来自这些 IP 地址的连接。

密码策略

确保您具有复杂的密码策略,以强制用户选择复杂的密码。 有关更多信息,请参阅 密码策略 章节。 通过设置 Keycloak 服务器以使用一次性密码来防止密码猜测。

只读用户属性

存储在 Keycloak 中的典型用户具有与其用户个人资料相关的各种属性。 这些属性包括电子邮件、名字或姓氏。 但是,用户也可能具有属性,这些属性不是典型的个人资料数据,而是元数据。 元数据属性通常对于用户应该是只读的,并且典型用户永远不应能够通过 Keycloak 用户界面或帐户 REST API 更新这些属性。 某些属性甚至对于管理员在通过管理 REST API 创建或更新用户时也应该是只读的。

元数据属性通常是以下组中的属性

  • 与用户存储提供程序相关的各种链接或元数据。 例如,在 LDAP 集成的情况下,LDAP_ID 属性包含用户在 LDAP 服务器中的 ID。

  • 用户存储提供的元数据。 例如,从 LDAP 提供的 createdTimestamp 应该始终对用户或管理员只读。

  • 与各种认证器相关的元数据。例如,KERBEROS_PRINCIPAL 属性可以包含特定用户的 Kerberos 主体名称。类似地,usercertificate 属性可以包含与用户和 X.509 证书中的数据绑定的元数据,这通常在启用 X.509 证书身份验证时使用。

  • 与应用程序/客户端的用户标识符相关的元数据。例如,saml.persistent.name.id.for.my_app 可以包含 SAML NameID,客户端应用程序 my_app 将使用它作为用户标识符。

  • 与授权策略相关的元数据,这些策略用于基于属性的访问控制 (ABAC)。这些属性的值可能用于授权决策。因此,重要的是用户无法更新这些属性。

从长远来看,Keycloak 将拥有一个适当的用户配置文件 SPI,这将允许对每个用户属性进行细粒度的配置。目前,此功能尚未完全可用。因此,Keycloak 具有内部用户属性列表,这些属性对于用户是只读的,对于在服务器级别配置的管理员也是只读的。

这是只读属性的列表,Keycloak 默认提供程序和功能在内部使用这些属性,因此始终是只读的

  • 对于用户:KERBEROS_PRINCIPAL, LDAP_ID, LDAP_ENTRY_DN, CREATED_TIMESTAMP, createTimestamp, modifyTimestamp, userCertificate, saml.persistent.name.id.for.*, ENABLED, EMAIL_VERIFIED

  • 对于管理员:KERBEROS_PRINCIPAL, LDAP_ID, LDAP_ENTRY_DN, CREATED_TIMESTAMP, createTimestamp, modifyTimestamp

系统管理员有一种方法可以向此列表添加其他属性。该配置目前在服务器级别可用。

您可以使用 spi-user-profile-declarative-user-profile-read-only-attributesspi-user-profile-declarative-user-profile-admin-read-only-attributes 选项添加此配置。例如

kc.[sh|bat] start --spi-user-profile-declarative-user-profile-read-only-attributes=foo,bar*

对于此示例,用户和管理员将无法更新属性 foo。用户将无法编辑任何以 bar 开头的属性。例如 barbarrier。配置不区分大小写,因此对于此示例,类似 FOOBarRier 的属性也将被拒绝。通配符 * 仅在属性名称末尾受支持,因此管理员可以有效地拒绝所有以指定字符开头的属性。属性名称中间的 * 被视为普通字符。

验证用户属性

借助 管理用户属性 中的功能,管理员可以限制用户为属性输入的数据,例如,在用户注册或帐户控制台中。

管理员不应允许用户使用非托管属性,以防止攻击者添加无限数量的属性。属性应具有验证,以限制攻击者输入的数据量。

当使用正则表达式验证用户属性时,请避免使用占用过多内存或 CPU 的正则表达式。有关详细信息,请参阅 OWASP 的正则表达式拒绝服务

点击劫持

点击劫持是一种欺骗用户点击与用户感知到的用户界面元素不同的技术。恶意站点将目标站点加载到透明的 iFrame 中,该 iFrame 覆盖在目标站点上重要按钮正下方的一组虚拟按钮之上。当用户单击可见按钮时,他们实际上单击的是隐藏页面上的按钮。攻击者可以使用此方法窃取用户的身份验证凭据并访问其资源。

默认情况下,Keycloak 的每个响应都会设置一些特定的 HTTP 标头,以防止这种情况发生。具体来说,它设置了 X-Frame-OptionsContent-Security-Policy。您应该查看这两个标头的定义,因为您可以控制许多细粒度的浏览器访问。

步骤

在管理控制台中,您可以指定 X-Frame-Options 和 Content-Security-Policy 标头的值。

  1. 单击领域设置菜单项。

  2. 单击 安全防御 选项卡。

    安全防御

    Security Defenses

默认情况下,Keycloak 仅为 iframe 设置 同源 策略。

SSL/HTTPS 要求

OAuth 2.0/OpenID Connect 使用访问令牌进行安全保护。攻击者可以扫描您的网络以查找访问令牌,并使用它们执行令牌具有权限的恶意操作。这种攻击被称为中间人攻击。在 Keycloak 身份验证服务器和 Keycloak 保护的客户端之间的通信中使用 SSL/HTTPS,以防止中间人攻击。

Keycloak 具有 三种 SSL/HTTPS 模式。SSL 设置起来很复杂,因此 Keycloak 允许通过私有 IP 地址(例如 localhost、192.168.x.x 和其他私有 IP 地址)进行非 HTTPS 通信。在生产环境中,请确保启用 SSL,并且 SSL 对于所有操作都是强制性的。

在适配器/客户端侧,您可以禁用 SSL 信任管理器。信任管理器确保 Keycloak 通信的客户端身份有效,并确保 DNS 域名与服务器证书一致。在生产环境中,请确保您的每个客户端适配器都使用信任存储,以防止 DNS 中间人攻击。

CSRF 攻击

跨站请求伪造 (CSRF) 攻击使用来自网站已验证用户的 HTTP 请求。任何使用基于 Cookie 的身份验证的站点都容易受到 CSRF 攻击。您可以通过将状态 Cookie 与发布的表单或查询参数进行匹配来缓解这些攻击。

OAuth 2.0 登录规范要求状态 Cookie 与传输的状态参数匹配。Keycloak 完全实现了规范的这一部分,因此所有登录都受到保护。

Keycloak 管理控制台是一个 JavaScript/HTML5 应用程序,它对后端 Keycloak 管理 REST API 进行 REST 调用。这些调用都需要持有者令牌身份验证,并且由 JavaScript Ajax 调用组成,因此 CSRF 是不可能的。您可以配置管理 REST API 以验证 CORS 来源。

Keycloak 中的帐户控制台可能容易受到 CSRF 攻击。为了防止 CSRF 攻击,Keycloak 设置了一个状态 Cookie,并将此 Cookie 的值嵌入到操作链接中的隐藏表单字段或查询参数中。Keycloak 检查查询/表单参数与状态 Cookie,以验证是否是同一用户发起的调用。

不明确的重定向 URI

使您注册的重定向 URI 尽可能具体。为 授权码流程 注册模糊的重定向 URI 可能会允许恶意客户端冒充另一个具有更广泛访问权限的客户端。例如,如果两个客户端位于同一域名下,则可能发生冒充。

您可以为您的领域使用安全重定向 uri 执行器。结果确保客户端管理员只能注册具有特定重定向 uri 的客户端,这些 uri 符合各种要求,例如要求 URL 在上下文路径中不能有通配符,或者可以限制为指定的允许域。有关如何使用特定执行器配置客户端策略的详细信息,请参阅 客户端策略

FAPI 合规性

为了确保 Keycloak 服务器将验证您的客户端是否更安全且符合 FAPI,您可以为 FAPI 支持配置客户端策略。FAPI 详细信息在 保护应用程序 部分中描述。除其他事项外,这确保了一些上述安全最佳实践,例如客户端所需的 SSL、使用的安全重定向 URI 以及更多类似的最佳实践。

OAuth 2.1 合规性

为了确保 Keycloak 服务器将验证您的客户端是否更安全且符合 OAuth 2.1,您可以为 OAuth 2.1 支持配置客户端策略。OAuth 2.1 详细信息在 保护应用程序 部分中描述。

泄露的访问令牌和刷新令牌

Keycloak 包含多项操作,以防止恶意行为者窃取访问令牌和刷新令牌。关键操作是强制 Keycloak 与其客户端和应用程序之间的 SSL/HTTPS 通信。默认情况下,Keycloak 不启用 SSL。

缓解泄露的访问令牌造成的损害的另一项操作是缩短令牌的生命周期。您可以在 超时页面 中指定令牌生命周期。访问令牌的短生命周期迫使客户端和应用程序在短时间后刷新其访问令牌。如果管理员检测到泄漏,则管理员可以注销所有用户会话以使这些刷新令牌无效,或设置撤销策略。

确保刷新令牌始终对客户端保持私有,并且永远不会被传输。

您可以通过将这些令牌作为持有者密钥令牌颁发来减轻泄露的访问令牌和刷新令牌造成的损害。有关更多信息,请参阅 OAuth 2.0 相互 TLS 客户端证书绑定访问令牌

如果访问令牌或刷新令牌泄露,请访问管理控制台并将不早于撤销策略推送到所有应用程序。推送不早于策略可确保在该时间之前颁发的任何令牌都变为无效。推送新的不早于策略可确保应用程序必须从 Keycloak 下载新的公钥,并减轻来自泄露的领域签名密钥的损害。有关更多信息,请参阅 密钥章节

如果特定应用程序、客户端或用户遭到泄露,您可以禁用它们。

泄露的授权码

对于 OIDC 授权码流程,Keycloak 为其授权码生成加密强度高的随机值。授权码仅使用一次以获取访问令牌。

在管理控制台的超时页面上,您可以指定授权码的有效时长。确保时长少于 10 秒,这足以让客户端从代码请求令牌。

您还可以通过对客户端应用 代码交换的 Proof Key (PKCE) 来防御泄露的授权码。

开放重定向器

开放重定向器是一个端点,它使用参数自动将用户代理重定向到参数值指定的位置,而无需验证。攻击者可以使用最终用户授权端点和重定向 URI 参数,将授权服务器用作开放重定向器,利用用户对授权服务器的信任来发起网络钓鱼攻击。

Keycloak 要求所有注册的应用程序和客户端至少注册一个重定向 URI 模式。当客户端请求 Keycloak 执行重定向时,Keycloak 会根据有效注册的 URI 模式列表检查重定向 URI。客户端和应用程序必须注册尽可能具体的 URI 模式,以缓解开放重定向器攻击。

如果应用程序需要非 http(s) 自定义方案,则它应是验证模式的显式部分(例如 custom:/app/*)。出于安全原因,像 * 这样的通用模式不涵盖非 http(s) 方案。

通过使用 客户端策略,管理员可以确保客户端无法注册开放重定向 URL,例如 *

密码数据库泄露

Keycloak 不以原始文本形式存储密码,而是以哈希文本形式存储,使用 PBKDF2-HMAC-SHA512 消息摘要算法。Keycloak 执行 210,000 次哈希迭代,这是安全社区推荐的迭代次数。如此多的哈希迭代次数可能会对性能产生不利影响,因为 PBKDF2 哈希会使用大量的 CPU 资源。

限制范围

默认情况下,新的客户端应用程序具有无限制的角色范围映射。该客户端的每个访问令牌都包含用户拥有的所有权限。如果攻击者入侵客户端并获得客户端的访问令牌,则用户可以访问的每个系统都会受到威胁。

通过对每个客户端使用范围菜单来限制访问令牌的角色。或者,您可以在客户端范围级别设置角色范围映射,并通过使用客户端范围菜单将客户端范围分配给您的客户端。

限制令牌受众

在服务之间信任度较低的环境中,限制令牌上的受众。有关更多信息,请参阅 OAuth2 威胁模型受众支持 部分。

限制身份验证会话

身份验证会话跟踪身份验证的状态。以下文本适用于任何来源流程。

本节介绍使用 Infinispan 提供程序进行身份验证会话的部署。

身份验证会话在内部存储为 RootAuthenticationSessionEntity。每个 RootAuthenticationSessionEntity 可以在 RootAuthenticationSessionEntity 中存储多个身份验证子会话,作为 AuthenticationSessionEntity 对象的集合。Keycloak 将身份验证会话存储在专用的 Infinispan 缓存中。每个 RootAuthenticationSessionEntityAuthenticationSessionEntity 数量会影响每个缓存条目的大小。身份验证会话缓存的总内存占用由存储的 RootAuthenticationSessionEntity 数量以及每个 RootAuthenticationSessionEntityAuthenticationSessionEntity 的数量决定。

维护的 RootAuthenticationSessionEntity 对象数量对应于来自浏览器的未完成登录流程的数量。为了控制 RootAuthenticationSessionEntity 的数量,建议使用高级防火墙控制来限制入口网络流量。

对于存在许多活动的 RootAuthenticationSessionEntity 和大量 AuthenticationSessionEntity 的部署,可能会出现更高的内存使用率。如果负载均衡器不支持或未配置会话粘性,则集群中网络上的负载可能会显着增加。此负载的原因是,每个落在不拥有相应身份验证会话的节点上的请求都需要在所有者节点中检索和更新身份验证会话记录,这涉及检索和存储的单独网络传输。

每个 RootAuthenticationSessionEntity 的最大 AuthenticationSessionEntity 数量可以在 authenticationSessions SPI 中通过设置属性 authSessionsLimit 进行配置。默认值设置为每个 RootAuthenticationSessionEntity 300 个 AuthenticationSessionEntity。当达到此限制时,在新的身份验证会话请求后,将删除最旧的身份验证子会话。

以下示例显示如何将每个 RootAuthenticationSessionEntity 的活动 AuthenticationSessionEntity 数量限制为 100。

bin/kc.[sh|bat] start --spi-authentication-sessions-infinispan-auth-sessions-limit=100

新映射存储的等效命令

bin/kc.[sh|bat] start --spi-authentication-sessions-map-auth-sessions-limit=100

SQL 注入攻击

目前,Keycloak 没有已知的 SQL 注入漏洞。

账户控制台

Keycloak 用户可以通过账户控制台管理他们的账户。他们可以配置个人资料、添加双因素身份验证、包含身份提供商账户以及监督设备活动。

附加资源
  • 账户控制台可以在外观和语言偏好方面进行配置。一个示例是将其他属性添加到个人信息页面。有关更多信息,请参阅服务器开发者指南

访问账户控制台

步骤
  1. 记下您的账户所在的 Keycloak 服务器的 realm 名称和 IP 地址。

  2. 在 Web 浏览器中,输入此格式的 URL:server-root/realms/{realm-name}/account。

  3. 输入您的登录名和密码。

帐户控制台

Account Console

您还可以在调用账户控制台 URL 时通过设置 scope 参数来请求其他范围,格式如下:server-root/realms/{realm-name}/account?scope=phone。

配置登录方式

您可以使用基本身份验证(登录名和密码)或双因素身份验证登录此控制台。对于双因素身份验证,请使用以下步骤之一。

使用 OTP 进行双因素身份验证

先决条件
  • OTP 是您的 realm 的有效身份验证机制。

步骤
  1. 单击菜单中的账户安全

  2. 单击登录

  3. 单击设置 Authenticator 应用程序

    登录

    Signing in

  4. 按照屏幕上出现的指示使用您的移动设备作为您的 OTP 生成器。

  5. 将屏幕截图中的 QR 码扫描到您移动设备上的 OTP 生成器中。

  6. 注销并重新登录。

  7. 通过输入您的移动设备上提供的 OTP 来响应提示。

使用 WebAuthn 进行双因素身份验证

先决条件
  • WebAuthn 是您的 realm 的有效双因素身份验证机制。请关注 WebAuthn 部分以了解更多详情。

步骤
  1. 单击菜单中的账户安全

  2. 单击登录

  3. 单击设置通行密钥

    登录

    Signing in with a Passkey

  4. 准备您的通行密钥。如何准备此密钥取决于您使用的通行密钥类型。例如,对于基于 USB 的 Yubikey,您可能需要将密钥插入笔记本电脑上的 USB 端口。

  5. 单击注册以注册您的通行密钥。

  6. 注销并重新登录。

  7. 假设身份验证流程设置正确,则会出现一条消息,要求您使用通行密钥作为第二因素进行身份验证。

使用 WebAuthn 进行无密码身份验证

先决条件
  • WebAuthn 是您的 realm 的有效无密码身份验证机制。请关注 无密码 WebAuthn 部分以了解更多详情。

步骤
  1. 单击菜单中的账户安全

  2. 单击登录

  3. 无密码部分中,单击设置通行密钥

    登录

    Signing in with a Passkey

  4. 准备您的通行密钥。如何准备此密钥取决于您使用的通行密钥类型。例如,对于基于 USB 的 Yubikey,您可能需要将密钥插入笔记本电脑上的 USB 端口。

  5. 单击注册以注册您的通行密钥。

  6. 注销并重新登录。

  7. 假设身份验证流程设置正确,则会出现一条消息,要求您使用通行密钥作为第二因素进行身份验证。您不再需要提供密码即可登录。

查看设备活动

您可以查看已登录到您账户的设备。

步骤
  1. 单击菜单中的账户安全

  2. 单击设备活动

  3. 如果设备看起来可疑,请注销该设备。

设备

Devices

添加身份提供商账户

您可以将您的账户与身份代理链接。此选项通常用于链接社交提供商账户。

步骤
  1. 登录到管理控制台。

  2. 单击菜单中的身份提供商

  3. 选择提供商并填写字段。

  4. 返回到账户控制台。

  5. 单击菜单中的账户安全

  6. 单击关联账户

您添加的身份提供商将出现在此页面中。

关联账户

Linked Accounts

访问其他应用程序

应用程序菜单项向用户显示您可以访问哪些应用程序。在本例中,仅账户控制台可用。

应用程序

Applications

查看组成员资格

您可以通过单击菜单来查看与您关联的组。如果您选中直接成员复选框,您将仅看到与您直接关联的组。

先决条件
  • 您需要拥有 view-groups 账户角色才能查看菜单。

查看组成员资格

View group memberships

Admin CLI

借助 Keycloak,您可以使用 Admin CLI 命令行工具从命令行界面 (CLI) 执行管理任务。

安装 Admin CLI

Keycloak 将 Admin CLI 服务器发行包与 bin 目录中的执行脚本打包在一起。

Linux 脚本称为 kcadm.sh,Windows 脚本称为 kcadm.bat。将 Keycloak 服务器目录添加到您的 PATH,以便从文件系统上的任何位置使用客户端。

例如

  • Linux

    $ export PATH=$PATH:$KEYCLOAK_HOME/bin
    $ kcadm.sh
  • Windows

    c:\> set PATH=%PATH%;%KEYCLOAK_HOME%\bin
    c:\> kcadm

您必须将 KEYCLOAK_HOME 环境变量设置为您解压 Keycloak Server 发行包的路径。

为避免重复,本文档的其余部分仅在 CLI 差异不仅仅在于 kcadm 命令名称的情况下使用 Windows 示例。

使用 Admin CLI

Admin CLI 向 Admin REST 端点发出 HTTP 请求。访问 Admin REST 端点需要身份验证。

有关特定端点的 JSON 属性的详细信息,请参阅 Admin REST API 文档。

  1. 通过登录启动经过身份验证的会话。现在,您可以执行创建、读取、更新和删除 (CRUD) 操作。

    例如

    • Linux

      $ kcadm.sh config credentials --server https://#:8080 --realm demo --user admin --client admin
      $ kcadm.sh create realms -s realm=demorealm -s enabled=true -o
      $ CID=$(kcadm.sh create clients -r demorealm -s clientId=my_client -s 'redirectUris=["https://#:8980/myapp/*"]' -i)
      $ kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json
    • Windows

      c:\> kcadm config credentials --server https://#:8080 --realm demo --user admin --client admin
      c:\> kcadm create realms -s realm=demorealm -s enabled=true -o
      c:\> kcadm create clients -r demorealm -s clientId=my_client -s "redirectUris=[\"https://#:8980/myapp/*\"]" -i > clientid.txt
      c:\> set /p CID=<clientid.txt
      c:\> kcadm get clients/%CID%/installation/providers/keycloak-oidc-keycloak-json
  2. 在生产环境中,请使用 https: 访问 Keycloak,以避免泄露令牌。如果 Java 默认证书信任存储中包含的受信任证书颁发机构未颁发服务器证书,请准备一个 truststore.jks 文件,并指示 Admin CLI 使用它。

    例如

    • Linux

      $ kcadm.sh config truststore --trustpass $PASSWORD ~/.keycloak/truststore.jks
    • Windows

      c:\> kcadm config truststore --trustpass %PASSWORD% %HOMEPATH%\.keycloak\truststore.jks

敏感选项

敏感值(如密码)可以指定为命令选项。通常不建议这样做。还有一些机制,您可以通过省略选项或提供值来提示您输入敏感值。最后,所有这些都将有一个相应的环境变量可以代替使用。查看您正在运行的命令的帮助信息,以查看所有可能的选项。

身份验证

当您使用 Admin CLI 登录时,您需要指定

  • 服务器端点 URL

  • 用户名

另一个选项是仅指定 clientId,这将为您创建一个唯一的服务帐户供您使用。

当您使用用户名登录时,请使用指定用户的密码。当您使用 clientId 登录时,您只需要客户端密钥,而不需要用户密码。您也可以使用 Signed JWT 而不是客户端密钥。

确保用于会话的帐户具有调用 Admin REST API 操作的适当权限。例如,realm-management 客户端的 realm-admin 角色可以管理用户的域。

有两种主要的身份验证机制可用。一种机制使用 kcadm config credentials 启动经过身份验证的会话。

$ kcadm.sh config credentials --server https://#:8080 --realm master --user admin

此机制通过保存获得的访问令牌及其关联的刷新令牌,在 kcadm 命令调用之间维护经过身份验证的会话。它可以将其他密钥保存在私有配置文件中。有关更多信息,请参阅下一章

第二种机制在每次命令调用期间进行身份验证,用于该调用的持续时间。此机制会增加服务器的负载以及花费在往返获取令牌上的时间。这种方法的好处是不需要在调用之间保存令牌,因此不会保存到磁盘。当指定 --no-config 参数时,Keycloak 使用此模式。

例如,在执行操作时,请指定身份验证所需的所有信息。

$ kcadm.sh get realms --no-config --server https://#:8080 --realm master --user admin

运行 kcadm.sh help 命令,以获取有关使用 Admin CLI 的更多信息。

运行 kcadm.sh config credentials --help 命令,以获取有关启动经过身份验证的会话的更多信息。

如果您未指定 --password 选项(通常建议不要将密码作为命令的一部分提供),除非已将密码指定为环境变量 KC_CLI_PASSWORD,否则系统将提示您输入密码。

使用备用配置

默认情况下,Admin CLI 维护一个名为 kcadm.config 的配置文件。Keycloak 将此文件放置在用户的主目录中。在基于 Linux 的系统中,完整路径名为 $HOME/.keycloak/kcadm.config。在 Windows 中,完整路径名为 %HOMEPATH%\.keycloak\kcadm.config

您可以使用 --config 选项指向不同的文件或位置,以便您可以并行维护多个经过身份验证的会话。

从单个线程执行与单个配置文件绑定的操作。

确保配置文件对系统上的其他用户不可见。它包含必须保密的访问令牌和密钥。Keycloak 会自动创建 ~/.keycloak 目录及其内容,并具有适当的访问限制。如果目录已存在,Keycloak 不会更新目录的权限。

可以避免将密钥存储在配置文件中,但这很不方便,并且会增加令牌请求的数量。将 --no-config 选项与所有命令一起使用,并在每次调用 kcadm 时指定 config credentials 命令所需的身份验证信息。

基本操作和资源 URI

Admin CLI 可以通用地对 Admin REST API 端点执行 CRUD 操作,并提供简化特定任务的附加命令。

主要使用模式在此处列出

$ kcadm.sh create ENDPOINT [ARGUMENTS]
$ kcadm.sh get ENDPOINT [ARGUMENTS]
$ kcadm.sh update ENDPOINT [ARGUMENTS]
$ kcadm.sh delete ENDPOINT [ARGUMENTS]

creategetupdatedelete 命令分别映射到 HTTP 动词 POSTGETPUTDELETE。ENDPOINT 是目标资源 URI,可以是绝对的(以 http:https: 开头)或相对的,Keycloak 使用它来组合以下格式的绝对 URL

SERVER_URI/admin/realms/REALM/ENDPOINT

例如,如果您针对服务器 https://#:8080 进行身份验证,并且域为 master,则使用 users 作为 ENDPOINT 将创建 https://#:8080/admin/realms/master/users 资源 URL。

如果您将 ENDPOINT 设置为 clients,则有效的资源 URI 为 https://#:8080/admin/realms/master/clients

Keycloak 具有 realms 端点,它是域的容器。它解析为

SERVER_URI/admin/realms

Keycloak 具有 serverinfo 端点。此端点独立于域。

当您以具有 realm-admin 权限的用户身份进行身份验证时,您可能需要在多个域上执行命令。如果是这样,请指定 -r 选项以告知 CLI 要显式针对哪个域执行命令。命令将使用 TARGET_REALM,而不是使用 kcadm.sh config credentials--realm 选项指定的 REALM

SERVER_URI/admin/realms/TARGET_REALM/ENDPOINT

例如

$ kcadm.sh config credentials --server https://#:8080 --realm master --user admin
$ kcadm.sh create users -s username=testuser -s enabled=true -r demorealm

在此示例中,您启动一个会话,以 master 域中的 admin 用户身份进行身份验证。然后,您对资源 URL https://#:8080/admin/realms/demorealm/users 执行 POST 调用。

createupdate 命令将 JSON 正文发送到服务器。您可以使用 -f FILENAME 从文件中读取预先制作的文档。当您可以使用 -f - 选项时,Keycloak 会从标准输入中读取消息正文。您可以指定单个属性及其值,如 create users 示例中所示。Keycloak 将属性组合成 JSON 正文并将其发送到服务器。

在 name=value 对中使用的值(在 --set、-s 选项中使用)被假定为 JSON。如果无法解析为有效的 JSON,则会将其作为文本值发送到服务器。

如果值在 shell 处理后用引号括起来,但不是有效的 JSON,则引号将被剥离,并且值的其余部分将作为文本发送。此行为已弃用,请考虑不带引号指定您的值,或使用双引号指定有效的 JSON 字符串文字。

Keycloak 中有几种方法可用于使用 update 命令更新资源。您可以确定资源的当前状态并将其保存到文件中,编辑该文件,然后将其发送到服务器进行更新。

例如

$ kcadm.sh get realms/demorealm > demorealm.json
$ vi demorealm.json
$ kcadm.sh update realms/demorealm -f demorealm.json

此方法使用发送的 JSON 文档中的属性更新服务器上的资源。

另一种方法是通过使用 -s, --set 选项设置新值来执行即时更新。

例如

$ kcadm.sh update realms/demorealm -s enabled=false

此方法将 enabled 属性设置为 false

默认情况下,update 命令执行 get,然后将新属性值与现有值合并。在某些情况下,端点可能支持 put 命令,但不支持 get 命令。您可以使用 -n 选项执行无合并更新,这将执行 put 命令,而无需首先运行 get 命令。

域操作

创建新域

realms 端点上使用 create 命令来创建新的已启用域。将属性设置为 realmenabled

$ kcadm.sh create realms -s realm=demorealm -s enabled=true

Keycloak 默认禁用域。您可以通过启用域立即将其用于身份验证。

新对象的描述也可以是 JSON 格式。

$ kcadm.sh create realms -f demorealm.json

您可以直接从文件发送包含域属性的 JSON 文档,或将文档通过管道传递到标准输入。

例如

  • Linux

    $ kcadm.sh create realms -f - << EOF
    { "realm": "demorealm", "enabled": true }
    EOF
  • Windows

    c:\> echo { "realm": "demorealm", "enabled": true } | kcadm create realms -f -

列出现有域

此命令返回所有域的列表。

$ kcadm.sh get realms

Keycloak 在服务器上过滤域列表,以仅返回用户可以看到的域。

所有域属性的列表可能很冗长,并且大多数用户只对属性的子集感兴趣,例如域名和域的启用状态。您可以使用 --fields 选项指定要返回的属性。

$ kcadm.sh get realms --fields realm,enabled

您可以将结果显示为逗号分隔值。

$ kcadm.sh get realms --fields realm --format csv --noquotes

获取特定域

将域名附加到集合 URI 以获取单个域。

$ kcadm.sh get realms/master

更新域

  1. 当您不想更改所有域的属性时,请使用 -s 选项为属性设置新值。

    例如

    $ kcadm.sh update realms/demorealm -s enabled=false
  2. 如果您想将所有可写属性设置为新值

    1. 运行 get 命令。

    2. 编辑 JSON 文件中的当前值。

    3. 重新提交。

      例如

      $ kcadm.sh get realms/demorealm > demorealm.json
      $ vi demorealm.json
      $ kcadm.sh update realms/demorealm -f demorealm.json

删除域

运行以下命令以删除域

$ kcadm.sh delete realms/demorealm

为域启用所有登录页面选项

将控制特定功能的属性设置为 true

例如

$ kcadm.sh update realms/demorealm -s registrationAllowed=true -s registrationEmailAsUsername=true -s rememberMe=true -s verifyEmail=true -s resetPasswordAllowed=true -s editUsernameAllowed=true

列出域密钥

对目标域的 keys 端点使用 get 操作。

$ kcadm.sh get keys -r demorealm

生成新域密钥

  1. 在添加新的 RSA 生成的密钥对之前,获取目标域的 ID。

    例如

    $ kcadm.sh get realms/demorealm --fields id --format csv --noquotes
  2. 添加一个新的密钥提供程序,其优先级高于现有提供程序,如 kcadm.sh get keys -r demorealm 所示。

    例如

    • Linux

      $ kcadm.sh create components -r demorealm -s name=rsa-generated -s providerId=rsa-generated -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s 'config.priority=["101"]' -s 'config.enabled=["true"]' -s 'config.active=["true"]' -s 'config.keySize=["2048"]'
    • Windows

      c:\> kcadm create components -r demorealm -s name=rsa-generated -s providerId=rsa-generated -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s "config.priority=[\"101\"]" -s "config.enabled=[\"true\"]" -s "config.active=[\"true\"]" -s "config.keySize=[\"2048\"]"
  3. parentId 属性设置为目标域 ID 的值。

    新添加的密钥现在是活动密钥,如 kcadm.sh get keys -r demorealm 所示。

从 Java 密钥库文件添加新域密钥

  1. 添加一个新的密钥提供程序,以添加预先准备为 JKS 文件的新密钥对。

    例如,在

    • Linux

      $ kcadm.sh create components -r demorealm -s name=java-keystore -s providerId=java-keystore -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s 'config.priority=["101"]' -s 'config.enabled=["true"]' -s 'config.active=["true"]' -s 'config.keystore=["/opt/keycloak/keystore.jks"]' -s 'config.keystorePassword=["secret"]' -s 'config.keyPassword=["secret"]' -s 'config.keyAlias=["localhost"]'
    • Windows

      c:\> kcadm create components -r demorealm -s name=java-keystore -s providerId=java-keystore -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s "config.priority=[\"101\"]" -s "config.enabled=[\"true\"]" -s "config.active=[\"true\"]" -s "config.keystore=[\"/opt/keycloak/keystore.jks\"]" -s "config.keystorePassword=[\"secret\"]" -s "config.keyPassword=[\"secret\"]" -s "config.keyAlias=[\"localhost\"]"
  2. 确保您更改 keystorekeystorePasswordkeyPasswordalias 的属性值,以匹配您的特定密钥库。

  3. parentId 属性设置为目标域 ID 的值。

使密钥被动或禁用密钥

  1. 确定您要使其被动的密钥。

    $ kcadm.sh get keys -r demorealm
  2. 使用密钥的 providerId 属性构造端点 URI,例如 components/PROVIDER_ID

  3. 执行 update

    例如

    • Linux

      $ kcadm.sh update components/PROVIDER_ID -r demorealm -s 'config.active=["false"]'
    • Windows

      c:\> kcadm update components/PROVIDER_ID -r demorealm -s "config.active=[\"false\"]"

      您可以更新其他密钥属性

    • 设置新的 enabled 值以禁用密钥,例如,config.enabled=["false"]

    • 设置新的 priority 值以更改密钥的优先级,例如,config.priority=["110"]

删除旧密钥

  1. 确保您要删除的密钥处于非活动状态并且您已禁用它。此操作是为了防止应用程序和用户持有的现有令牌失败。

  2. 确定要删除的密钥。

    $ kcadm.sh get keys -r demorealm
  3. 使用密钥的 providerId 执行删除。

    $ kcadm.sh delete components/PROVIDER_ID -r demorealm

配置域的事件日志记录

events/config 端点使用 update 命令。

eventsListeners 属性包含 EventListenerProviderFactory ID 的列表,指定接收事件的所有事件侦听器。属性可用于控制内置事件存储,因此您可以使用 Admin REST API 查询过去的事件。Keycloak 对服务调用的日志记录 (eventsEnabled) 和由 Admin Console 或 Admin REST API 触发的审计事件 (adminEventsEnabled) 具有单独的控制。您可以设置 eventsExpiration 事件过期,以防止数据库被填满。Keycloak 将 eventsExpiration 设置为以秒为单位的生存时间。

您可以设置一个内置事件侦听器,该侦听器接收所有事件并通过 JBoss-logging 记录事件。使用 org.keycloak.events 记录器,Keycloak 将错误事件记录为 WARN,并将其他事件记录为 DEBUG

例如

  • Linux

    $ kcadm.sh update events/config -r demorealm -s 'eventsListeners=["jboss-logging"]'
  • Windows

    c:\> kcadm update events/config -r demorealm -s "eventsListeners=[\"jboss-logging\"]"

例如

您可以为所有可用的 ERROR 事件(不包括审计事件)开启两天的存储,以便您可以通过 Admin REST 检索事件。

  • Linux

    $ kcadm.sh update events/config -r demorealm -s eventsEnabled=true -s 'enabledEventTypes=["LOGIN_ERROR","REGISTER_ERROR","LOGOUT_ERROR","CODE_TO_TOKEN_ERROR","CLIENT_LOGIN_ERROR","FEDERATED_IDENTITY_LINK_ERROR","REMOVE_FEDERATED_IDENTITY_ERROR","UPDATE_EMAIL_ERROR","UPDATE_PROFILE_ERROR","UPDATE_PASSWORD_ERROR","UPDATE_TOTP_ERROR","UPDATE_CREDENTIAL_ERROR","VERIFY_EMAIL_ERROR","REMOVE_TOTP_ERROR","REMOVE_CREDENTIAL_ERROR","SEND_VERIFY_EMAIL_ERROR","SEND_RESET_PASSWORD_ERROR","SEND_IDENTITY_PROVIDER_LINK_ERROR","RESET_PASSWORD_ERROR","IDENTITY_PROVIDER_FIRST_LOGIN_ERROR","IDENTITY_PROVIDER_POST_LOGIN_ERROR","CUSTOM_REQUIRED_ACTION_ERROR","EXECUTE_ACTIONS_ERROR","CLIENT_REGISTER_ERROR","CLIENT_UPDATE_ERROR","CLIENT_DELETE_ERROR"]' -s eventsExpiration=172800
  • Windows

    c:\> kcadm update events/config -r demorealm -s eventsEnabled=true -s "enabledEventTypes=[\"LOGIN_ERROR\",\"REGISTER_ERROR\",\"LOGOUT_ERROR\",\"CODE_TO_TOKEN_ERROR\",\"CLIENT_LOGIN_ERROR\",\"FEDERATED_IDENTITY_LINK_ERROR\",\"REMOVE_FEDERATED_IDENTITY_ERROR\",\"UPDATE_EMAIL_ERROR\",\"UPDATE_PROFILE_ERROR\",\"UPDATE_PASSWORD_ERROR\",\"UPDATE_TOTP_ERROR\",\"UPDATE_CREDENTIAL_ERROR\",\"VERIFY_EMAIL_ERROR\",\"REMOVE_TOTP_ERROR\",\"REMOVE_CREDENTIAL_ERROR\",\"SEND_VERIFY_EMAIL_ERROR\",\"SEND_RESET_PASSWORD_ERROR\",\"SEND_IDENTITY_PROVIDER_LINK_ERROR\",\"RESET_PASSWORD_ERROR\",\"IDENTITY_PROVIDER_FIRST_LOGIN_ERROR\",\"IDENTITY_PROVIDER_POST_LOGIN_ERROR\",\"CUSTOM_REQUIRED_ACTION_ERROR\",\"EXECUTE_ACTIONS_ERROR\",\"CLIENT_REGISTER_ERROR\",\"CLIENT_UPDATE_ERROR\",\"CLIENT_DELETE_ERROR\"]" -s eventsExpiration=172800

您可以将存储的事件类型重置为所有可用的事件类型。将值设置为空列表与枚举所有类型相同。

$ kcadm.sh update events/config -r demorealm -s enabledEventTypes=[]

您可以启用审计事件的存储。

$ kcadm.sh update events/config -r demorealm -s adminEventsEnabled=true -s adminEventsDetailsEnabled=true

您可以获取最近 100 个事件。事件从最新到最旧排序。

$ kcadm.sh get events --offset 0 --limit 100

您可以删除所有已保存的事件。

$ kcadm delete events

刷新缓存

  1. 使用 create 命令和以下端点之一来清除缓存

    • clear-realm-cache

    • clear-user-cache

    • clear-keys-cache

  2. realm 设置为与目标域相同的值。

    例如

    $ kcadm.sh create clear-realm-cache -r demorealm -s realm=demorealm
    $ kcadm.sh create clear-user-cache -r demorealm -s realm=demorealm
    $ kcadm.sh create clear-keys-cache -r demorealm -s realm=demorealm

从导出的 .json 文件导入域

  1. partialImport 端点使用 create 命令。

  2. ifResourceExists 设置为 FAILSKIPOVERWRITE

  3. 使用 -f 提交导出的域 .json 文件。

    例如

    $ kcadm.sh create partialImport -r demorealm2 -s ifResourceExists=FAIL -o -f demorealm.json

    如果域尚不存在,请先创建它。

    例如

    $ kcadm.sh create realms -s realm=demorealm2 -s enabled=true

角色操作

创建域角色

使用 roles 端点创建域角色。

$ kcadm.sh create roles -r demorealm -s name=user -s 'description=Regular user with a limited set of permissions'

创建客户端角色

  1. 确定客户端。

  2. 使用 get 命令列出可用的客户端。

    $ kcadm.sh get clients -r demorealm --fields id,clientId
  3. 通过使用 clientId 属性构造端点 URI 来创建新角色,例如 clients/ID/roles

    例如

    $ kcadm.sh create clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles -r demorealm -s name=editor -s 'description=Editor can edit, and publish any article'

列出域角色

roles 端点使用 get 命令以列出现有的域角色。

$ kcadm.sh get roles -r demorealm

您也可以使用 get-roles 命令。

$ kcadm.sh get-roles -r demorealm

列出客户端角色

Keycloak 具有专用的 get-roles 命令,以简化域角色和客户端角色的列表。该命令是 get 命令的扩展,其行为与 get 命令相同,但具有列出角色的附加语义。

使用 get-roles 命令,方法是传递 clientId (--cclientid) 选项或 id (--cid) 选项来标识要列出客户端角色的客户端。

例如

$ kcadm.sh get-roles -r demorealm --cclientid realm-management

获取特定域角色

使用 get 命令和角色 name 来构造特定域角色的端点 URI,roles/ROLE_NAME,其中 user 是现有角色的名称。

例如

$ kcadm.sh get roles/user -r demorealm

您可以使用 get-roles 命令,方法是传递角色名称 (--rolename 选项) 或 ID (--roleid 选项)。

例如

$ kcadm.sh get-roles -r demorealm --rolename user

获取特定客户端角色

使用 get-roles 命令,方法是传递 clientId 属性 (--cclientid 选项) 或 ID 属性 (--cid 选项) 以标识客户端,并传递角色名称 (--rolename 选项) 或角色 ID 属性 (--roleid) 以标识特定的客户端角色。

例如

$ kcadm.sh get-roles -r demorealm --cclientid realm-management --rolename manage-clients

更新域角色

update 命令与您用于获取特定域角色的端点 URI 一起使用。

例如

$ kcadm.sh update roles/user -r demorealm -s 'description=Role representing a regular user'

更新客户端角色

update 命令与您用于获取特定客户端角色的端点 URI 一起使用。

例如

$ kcadm.sh update clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles/editor -r demorealm -s 'description=User that can edit, and publish articles'

删除域角色

delete 命令与您用于获取特定域角色的端点 URI 一起使用。

例如

$ kcadm.sh delete roles/user -r demorealm

删除客户端角色

delete 命令与您用于获取特定客户端角色的端点 URI 一起使用。

例如

$ kcadm.sh delete clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles/editor -r demorealm

列出复合角色的已分配、可用和有效域角色

使用 get-roles 命令列出组合角色的已分配、可用和有效域角色。

  1. 要列出组合角色的已分配域角色,请通过名称 (--rname 选项) 或 ID (--rid 选项) 指定目标组合角色。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole
  2. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole --effective
  3. 使用 --available 选项列出可以添加到组合角色中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole --available

列出组合角色的已分配、可用和有效客户端角色

使用 get-roles 命令列出组合角色的已分配、可用和有效客户端角色。

  1. 要列出组合角色的已分配客户端角色,您可以通过名称 (--rname 选项) 或 ID (--rid 选项) 指定目标组合角色,并通过 clientId 属性 (--cclientid 选项) 或 ID (--cid 选项) 指定客户端。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management
  2. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management --effective
  3. 使用 --available 选项列出可以添加到目标组合角色中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management --available

向组合角色添加域角色

Keycloak 提供了 add-roles 命令,用于添加域角色和客户端角色。

此示例将 user 角色添加到组合角色 testrole

$ kcadm.sh add-roles --rname testrole --rolename user -r demorealm

从组合角色中移除域角色

Keycloak 提供了 remove-roles 命令,用于移除域角色和客户端角色。

以下示例从目标组合角色 testrole 中移除 user 角色。

$ kcadm.sh remove-roles --rname testrole --rolename user -r demorealm

向域角色添加客户端角色

Keycloak 提供了 add-roles 命令,用于添加域角色和客户端角色。

以下示例将客户端 realm-management 上定义的角色 create-clientview-users 添加到 testrole 组合角色。

$ kcadm.sh add-roles -r demorealm --rname testrole --cclientid realm-management --rolename create-client --rolename view-users

向客户端角色添加客户端角色

  1. 通过使用 get-roles 命令确定组合客户端角色的 ID。

    例如

    $ kcadm.sh get-roles -r demorealm --cclientid test-client --rolename operations
  2. 假设存在一个客户端,其 clientId 属性名为 test-client,客户端角色名为 support,客户端角色名为 operations,后者成为 ID 为 "fc400897-ef6a-4e8c-872b-1581b7fa8a71" 的组合角色。

  3. 使用以下示例向组合角色添加另一个角色。

    $ kcadm.sh add-roles -r demorealm --cclientid test-client --rid fc400897-ef6a-4e8c-872b-1581b7fa8a71 --rolename support
  4. 使用 get-roles --all 命令列出组合角色的角色。

    例如

    $ kcadm.sh get-roles --rid fc400897-ef6a-4e8c-872b-1581b7fa8a71 --all

从组合角色中移除客户端角色

使用 remove-roles 命令从组合角色中移除客户端角色。

使用以下示例从组合角色 testrole 中移除客户端 realm-management 上定义的两个角色,即 create-client 角色和 view-users 角色。

$ kcadm.sh remove-roles -r demorealm --rname testrole --cclientid realm-management --rolename create-client --rolename view-users

向组添加客户端角色

使用 add-roles 命令添加域角色和客户端角色。

以下示例将客户端 realm-management 上定义的角色 create-clientview-users 添加到 Group 组 (--gname 选项)。或者,您可以通过 ID (--gid 选项) 指定组。

有关更多信息,请参阅 组操作

$ kcadm.sh add-roles -r demorealm --gname Group --cclientid realm-management --rolename create-client --rolename view-users

从组中移除客户端角色

使用 remove-roles 命令从组中移除客户端角色。

以下示例从 Group 组中移除客户端 realm-management 上定义的两个角色,即 create-clientview-users

有关更多信息,请参阅 组操作

$ kcadm.sh remove-roles -r demorealm --gname Group --cclientid realm-management --rolename create-client --rolename view-users

客户端操作

创建客户端

  1. clients 端点上运行 create 命令以创建新客户端。

    例如

    $ kcadm.sh create clients -r demorealm -s clientId=myapp -s enabled=true
  2. 如果需要为适配器设置用于身份验证的密钥,请指定密钥。

    例如

    $ kcadm.sh create clients -r demorealm -s clientId=myapp -s enabled=true -s clientAuthenticatorType=client-secret -s secret=d0b8122f-8dfb-46b7-b68a-f5cc4e25d000

列出客户端

使用 clients 端点上的 get 命令列出客户端。

此示例过滤输出,仅列出 idclientId 属性

$ kcadm.sh get clients -r demorealm --fields id,clientId

获取特定客户端

使用客户端 ID 构建指向特定客户端的端点 URI,例如 clients/ID

例如

$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm

获取特定客户端的当前密钥

使用客户端 ID 构建端点 URI,例如 clients/ID/client-secret

例如

$ kcadm.sh get clients/$CID/client-secret -r demorealm

为特定客户端生成新密钥

使用客户端 ID 构建端点 URI,例如 clients/ID/client-secret

例如

$ kcadm.sh create clients/$CID/client-secret -r demorealm

更新特定客户端的当前密钥

使用客户端 ID 构建端点 URI,例如 clients/ID

例如

$ kcadm.sh update clients/$CID -s "secret=newSecret" -r demorealm

获取特定客户端的适配器配置文件 (keycloak.json)

使用客户端 ID 构建指向特定客户端的端点 URI,例如 clients/ID/installation/providers/keycloak-oidc-keycloak-json

例如

$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3/installation/providers/keycloak-oidc-keycloak-json -r demorealm

获取特定客户端的 WildFly 子系统适配器配置

使用客户端 ID 构建指向特定客户端的端点 URI,例如 clients/ID/installation/providers/keycloak-oidc-jboss-subsystem

例如

$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3/installation/providers/keycloak-oidc-jboss-subsystem -r demorealm

获取特定客户端的 Docker-v2 示例配置

使用客户端 ID 构建指向特定客户端的端点 URI,例如 clients/ID/installation/providers/docker-v2-compose-yaml

响应为 .zip 格式。

例如

$ kcadm.sh get https://#:8080/admin/realms/demorealm/clients/8f271c35-44e3-446f-8953-b0893810ebe7/installation/providers/docker-v2-compose-yaml -r demorealm > keycloak-docker-compose-yaml.zip

更新客户端

使用 update 命令以及您用于获取特定客户端的相同端点 URI。

例如

  • Linux

    $ kcadm.sh update clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm -s enabled=false -s publicClient=true -s 'redirectUris=["https://#:8080/myapp/*"]' -s baseUrl=https://#:8080/myapp -s adminUrl=https://#:8080/myapp
  • Windows

    c:\> kcadm update clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm -s enabled=false -s publicClient=true -s "redirectUris=[\"https://#:8080/myapp/*\"]" -s baseUrl=https://#:8080/myapp -s adminUrl=https://#:8080/myapp

删除客户端

使用 delete 命令以及您用于获取特定客户端的相同端点 URI。

例如

$ kcadm.sh delete clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm

为客户端的服务帐户添加或移除角色

客户端的服务帐户是一个用户帐户,用户名为 service-account-CLIENT_ID。您可以对此帐户执行与常规帐户相同的用户操作。

用户操作

创建用户

users 端点上运行 create 命令以创建新用户。

例如

$ kcadm.sh create users -r demorealm -s username=testuser -s enabled=true

列出用户

使用 users 端点列出用户。目标用户下次登录时必须更改密码。

例如

$ kcadm.sh get users -r demorealm --offset 0 --limit 1000

您可以按 usernamefirstNamelastNameemail 过滤用户。

例如

$ kcadm.sh get users -r demorealm -q q=email:google.com
$ kcadm.sh get users -r demorealm -q q=username:testuser

过滤不使用精确匹配。此示例将 username 属性的值与 *testuser* 模式进行匹配。

对于客户端、组和用户,您可以通过指定更复杂的 q 查询参数跨多个属性进行过滤。您可以像这样使用 -q q="field1:value1 field2:value2"。Keycloak 仅返回与所有属性的条件都匹配的用户。

获取特定用户

使用用户 ID 构建端点 URI,例如 users/USER_ID

例如

$ kcadm.sh get users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm

更新用户

使用 update 命令以及您用于获取特定用户的相同端点 URI。

例如

  • Linux

    $ kcadm.sh update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm -s 'requiredActions=["VERIFY_EMAIL","UPDATE_PROFILE","CONFIGURE_TOTP","UPDATE_PASSWORD"]'
  • Windows

    c:\> kcadm update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm -s "requiredActions=[\"VERIFY_EMAIL\",\"UPDATE_PROFILE\",\"CONFIGURE_TOTP\",\"UPDATE_PASSWORD\"]"

删除用户

使用 delete 命令以及您用于获取特定用户的相同端点 URI。

例如

$ kcadm.sh delete users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm

重置用户密码

使用专用的 set-password 命令重置用户密码。

例如

$ kcadm.sh set-password -r demorealm --username testuser --new-password NEWPASSWORD --temporary

此命令为用户设置临时密码。目标用户下次登录时必须更改密码。

您可以使用 --userid 通过使用 id 属性来指定用户。

您可以使用在从用于获取特定用户的端点构建的端点上使用 update 命令来实现相同的结果,例如 users/USER_ID/reset-password

例如

$ kcadm.sh update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2/reset-password -r demorealm -s type=password -s value=NEWPASSWORD -s temporary=true -n

-n 参数确保 Keycloak 执行 PUT 命令,而无需在 PUT 命令之前执行 GET 命令。这是必要的,因为 reset-password 端点不支持 GET

列出用户的已分配、可用和有效域角色

您可以使用 get-roles 命令列出用户的已分配、可用和有效域角色。

  1. 通过用户名或 ID 指定目标用户,以列出用户的已分配域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser
  2. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser --effective
  3. 使用 --available 选项列出可以添加到用户中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser --available

列出用户的已分配、可用和有效客户端角色

使用 get-roles 命令列出用户的已分配、可用和有效客户端角色。

  1. 通过用户名 (--uusername 选项) 或 ID (--uid 选项) 指定目标用户,并通过 clientId 属性 (--cclientid 选项) 或 ID (--cid 选项) 指定客户端,以列出用户的已分配客户端角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management
  2. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management --effective
  3. 使用 --available 选项列出可以添加到用户中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management --available

向用户添加域角色

使用 add-roles 命令向用户添加域角色。

使用以下示例将 user 角色添加到用户 testuser

$ kcadm.sh add-roles --uusername testuser --rolename user -r demorealm

从用户中移除域角色

使用 remove-roles 命令从用户中移除域角色。

使用以下示例从用户 testuser 中移除 user 角色

$ kcadm.sh remove-roles --uusername testuser --rolename user -r demorealm

向用户添加客户端角色

使用 add-roles 命令向用户添加客户端角色。

使用以下示例将客户端 realm-management 上定义的两个角色,即 create-client 角色和 view-users 角色,添加到用户 testuser

$ kcadm.sh add-roles -r demorealm --uusername testuser --cclientid realm-management --rolename create-client --rolename view-users

从用户中移除客户端角色

使用 remove-roles 命令从用户中移除客户端角色。

使用以下示例从 realm-management 客户端移除两个角色

$ kcadm.sh remove-roles -r demorealm --uusername testuser --cclientid realm-management --rolename create-client --rolename view-users

列出用户的会话

  1. 确定用户的 ID,

  2. 使用 ID 构建端点 URI,例如 users/ID/sessions

  3. 使用 get 命令检索用户会话的列表。

    例如

    $ kcadm.sh get users/6da5ab89-3397-4205-afaa-e201ff638f9e/sessions -r demorealm

从特定会话中注销用户

  1. 如前所述,确定会话的 ID。

  2. 使用会话的 ID 构建端点 URI,例如 sessions/ID

  3. 使用 delete 命令使会话失效。

    例如

    $ kcadm.sh delete sessions/d0eaa7cc-8c5d-489d-811a-69d3c4ec84d1 -r demorealm

从所有会话中注销用户

使用用户的 ID 构建端点 URI,例如 users/ID/logout

使用 create 命令对该端点 URI 执行 POST

例如

$ kcadm.sh create users/6da5ab89-3397-4205-afaa-e201ff638f9e/logout -r demorealm -s realm=demorealm -s user=6da5ab89-3397-4205-afaa-e201ff638f9e

组操作

创建组

groups 端点上使用 create 命令以创建新组。

例如

$ kcadm.sh create groups -r demorealm -s name=Group

列出组

groups 端点上使用 get 命令以列出组。

例如

$ kcadm.sh get groups -r demorealm

获取特定组

使用组的 ID 构建端点 URI,例如 groups/GROUP_ID

例如

$ kcadm.sh get groups/51204821-0580-46db-8f2d-27106c6b5ded -r demorealm

更新组

使用 update 命令以及您用于获取特定组的相同端点 URI。

例如

$ kcadm.sh update groups/51204821-0580-46db-8f2d-27106c6b5ded -s 'attributes.email=["group@example.com"]' -r demorealm

删除组

使用 delete 命令以及您用于获取特定组的相同端点 URI。

例如

$ kcadm.sh delete groups/51204821-0580-46db-8f2d-27106c6b5ded -r demorealm

创建子组

通过列出组查找父组的 ID。使用该 ID 构建端点 URI,例如 groups/GROUP_ID/children

例如

$ kcadm.sh create groups/51204821-0580-46db-8f2d-27106c6b5ded/children -r demorealm -s name=SubGroup

将组移动到另一个组下

  1. 查找现有父组的 ID 和现有子组的 ID。

  2. 使用父组的 ID 构建端点 URI,例如 groups/PARENT_GROUP_ID/children

  3. 在此端点上运行 create 命令,并将子组的 ID 作为 JSON 正文传递。

例如

$ kcadm.sh create groups/51204821-0580-46db-8f2d-27106c6b5ded/children -r demorealm -s id=08d410c6-d585-4059-bb07-54dcb92c5094 -s name=SubGroup

获取特定用户的组

使用用户的 ID 确定用户在组中的成员身份,以构建端点 URI,例如 users/USER_ID/groups

例如

$ kcadm.sh get users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups -r demorealm

将用户添加到组

使用 update 命令以及由用户 ID 和组 ID 组成的端点 URI,例如 users/USER_ID/groups/GROUP_ID,将用户添加到组。

例如

$ kcadm.sh update users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups/ce01117a-7426-4670-a29a-5c118056fe20 -r demorealm -s realm=demorealm -s userId=b544f379-5fc4-49e5-8a8d-5cfb71f46f53 -s groupId=ce01117a-7426-4670-a29a-5c118056fe20 -n

从组中移除用户

在用于将用户添加到组的相同端点 URI 上使用 delete 命令,例如 users/USER_ID/groups/GROUP_ID,以从组中移除用户。

例如

$ kcadm.sh delete users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups/ce01117a-7426-4670-a29a-5c118056fe20 -r demorealm

列出组的已分配、可用和有效域角色

使用专用的 get-roles 命令列出组的已分配、可用和有效域角色。

  1. 通过名称 (--gname 选项)、路径 (--gpath 选项) 或 ID (--gid 选项) 指定目标组,以列出组的已分配域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group
  2. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group --effective
  3. 使用 --available 选项列出可以添加到组中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group --available

列出组的已分配、可用和有效客户端角色

使用 get-roles 命令列出组的已分配、可用和有效客户端角色。

  1. 通过名称 (--gname 选项) 或 ID (--gid 选项) 指定目标组,

  2. 通过 clientId 属性 (--cclientid 选项) 或 ID (--id 选项) 指定客户端,以列出用户的已分配客户端角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management
  3. 使用 --effective 选项列出有效域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management --effective
  4. 使用 --available 选项列出您仍然可以添加到组中的域角色。

    例如

    $ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management --available

身份提供者操作

列出可用的身份提供者

使用 serverinfo 端点列出可用的身份提供者。

例如

$ kcadm.sh get serverinfo -r demorealm --fields 'identityProviders(*)'

Keycloak 处理 serverinfo 端点的方式与 realms 端点类似。Keycloak 不会相对于目标域解析端点,因为它存在于任何特定域之外。

列出已配置的身份提供者

使用 identity-provider/instances 端点。

例如

$ kcadm.sh get identity-provider/instances -r demorealm --fields alias,providerId,enabled

获取特定的已配置身份提供者

使用身份提供者的 alias 属性构建端点 URI,例如 identity-provider/instances/ALIAS,以获取特定的身份提供者。

例如

$ kcadm.sh get identity-provider/instances/facebook -r demorealm

移除特定的已配置身份提供者

使用 delete 命令以及您用于获取特定已配置身份提供者的相同端点 URI,以移除特定的已配置身份提供者。

例如

$ kcadm.sh delete identity-provider/instances/facebook -r demorealm

配置 Keycloak OpenID Connect 身份提供者

  1. 在创建新的身份提供者实例时,使用 keycloak-oidc 作为 providerId

  2. 提供 config 属性:authorizationUrltokenUrlclientIdclientSecret

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=keycloak-oidc -s providerId=keycloak-oidc -s enabled=true -s 'config.useJwksUrl="true"' -s config.authorizationUrl=https://#:8180/realms/demorealm/protocol/openid-connect/auth -s config.tokenUrl=https://#:8180/realms/demorealm/protocol/openid-connect/token -s config.clientId=demo-oidc-provider -s config.clientSecret=secret

配置 OpenID Connect 身份提供者

配置通用的 OpenID Connect 提供者的方式与配置 Keycloak OpenID Connect 提供者的方式相同,不同之处在于您将 providerId 属性值设置为 oidc

配置 SAML 2 身份提供者

  1. 使用 saml 作为 providerId

  2. 提供 config 属性:singleSignOnServiceUrlnameIDPolicyFormatsignatureAlgorithm

例如

$ kcadm.sh create identity-provider/instances -r demorealm -s alias=saml -s providerId=saml -s enabled=true -s 'config.useJwksUrl="true"' -s config.singleSignOnServiceUrl=https://#:8180/realms/saml-broker-realm/protocol/saml -s config.nameIDPolicyFormat=urn:oasis:names:tc:SAML:2.0:nameid-format:persistent -s config.signatureAlgorithm=RSA_SHA256

配置 Facebook 身份提供者

  1. 使用 facebook 作为 providerId

  2. 提供 config 属性:clientIdclientSecret。您可以在 Facebook 开发者应用程序配置页面中找到这些属性,用于您的应用程序。有关更多信息,请参阅 Facebook 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=facebook -s providerId=facebook -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=FACEBOOK_CLIENT_ID -s config.clientSecret=FACEBOOK_CLIENT_SECRET

配置 Google 身份提供者

  1. 使用 google 作为 providerId

  2. 提供 config 属性:clientIdclientSecret。您可以在 Google 开发者应用程序配置页面中找到这些属性,用于您的应用程序。有关更多信息,请参阅 Google 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=google -s providerId=google -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=GOOGLE_CLIENT_ID -s config.clientSecret=GOOGLE_CLIENT_SECRET

配置 Twitter 身份提供者

  1. 使用 twitter 作为 providerId

  2. 提供 config 属性 clientIdclientSecret。您可以在 Twitter 应用程序管理应用程序配置页面中找到这些属性,用于您的应用程序。有关更多信息,请参阅 Twitter 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=google -s providerId=google -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=TWITTER_API_KEY -s config.clientSecret=TWITTER_API_SECRET

配置 GitHub 身份提供者

  1. 使用 github 作为 providerId

  2. 提供 config 属性 clientIdclientSecret。您可以在 GitHub 开发者应用程序设置页面中找到您应用程序的这些属性。有关更多信息,请参阅 GitHub 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=github -s providerId=github -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=GITHUB_CLIENT_ID -s config.clientSecret=GITHUB_CLIENT_SECRET

配置 LinkedIn 身份提供程序

  1. 使用 linkedin 作为 providerId

  2. 提供 config 属性 clientIdclientSecret。您可以在 LinkedIn 开发者控制台应用程序页面中找到您应用程序的这些属性。有关更多信息,请参阅 LinkedIn 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=linkedin -s providerId=linkedin -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=LINKEDIN_CLIENT_ID -s config.clientSecret=LINKEDIN_CLIENT_SECRET

配置 Microsoft Live 身份提供程序

  1. 使用 microsoft 作为 providerId

  2. 提供 config 属性 clientIdclientSecret。您可以在 Microsoft 应用程序注册门户页面中找到您应用程序的这些属性。有关更多信息,请参阅 Microsoft 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=microsoft -s providerId=microsoft -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=MICROSOFT_APP_ID -s config.clientSecret=MICROSOFT_PASSWORD

配置 Stack Overflow 身份提供程序

  1. 使用 stackoverflow 命令作为 providerId

  2. 提供 config 属性 clientIdclientSecretkey。您可以在 Stack Apps OAuth 页面中找到您应用程序的这些属性。有关更多信息,请参阅 Stack Overflow 身份代理 页面。

    例如

    $ kcadm.sh create identity-provider/instances -r demorealm -s alias=stackoverflow -s providerId=stackoverflow -s enabled=true  -s 'config.useJwksUrl="true"' -s config.clientId=STACKAPPS_CLIENT_ID -s config.clientSecret=STACKAPPS_CLIENT_SECRET -s config.key=STACKAPPS_KEY

存储提供程序操作

配置 Kerberos 存储提供程序

  1. components 端点使用 create 命令。

  2. 将域 ID 指定为 parentId 属性的值。

  3. kerberos 指定为 providerId 属性的值,并将 org.keycloak.storage.UserStorageProvider 指定为 providerType 属性的值。

  4. 例如

    $ kcadm.sh create components -r demorealm -s parentId=demorealmId -s id=demokerberos -s name=demokerberos -s providerId=kerberos -s providerType=org.keycloak.storage.UserStorageProvider -s 'config.priority=["0"]' -s 'config.debug=["false"]' -s 'config.allowPasswordAuthentication=["true"]' -s 'config.editMode=["UNSYNCED"]' -s 'config.updateProfileFirstLogin=["true"]' -s 'config.allowKerberosAuthentication=["true"]' -s 'config.kerberosRealm=["KEYCLOAK.ORG"]' -s 'config.keyTab=["http.keytab"]' -s 'config.serverPrincipal=["HTTP/localhost@KEYCLOAK.ORG"]' -s 'config.cachePolicy=["DEFAULT"]'

配置 LDAP 用户存储提供程序

  1. components 端点使用 create 命令。

  2. ldap 指定为 providerId 属性的值,并将 org.keycloak.storage.UserStorageProvider 指定为 providerType 属性的值。

  3. 将域 ID 作为 parentId 属性的值提供。

  4. 使用以下示例创建 Kerberos 集成的 LDAP 提供程序。

    $ kcadm.sh create components -r demorealm -s name=kerberos-ldap-provider -s providerId=ldap -s providerType=org.keycloak.storage.UserStorageProvider -s parentId=3d9c572b-8f33-483f-98a6-8bb421667867  -s 'config.priority=["1"]' -s 'config.fullSyncPeriod=["-1"]' -s 'config.changedSyncPeriod=["-1"]' -s 'config.cachePolicy=["DEFAULT"]' -s config.evictionDay=[] -s config.evictionHour=[] -s config.evictionMinute=[] -s config.maxLifespan=[] -s 'config.batchSizeForSync=["1000"]' -s 'config.editMode=["WRITABLE"]' -s 'config.syncRegistrations=["false"]' -s 'config.vendor=["other"]' -s 'config.usernameLDAPAttribute=["uid"]' -s 'config.rdnLDAPAttribute=["uid"]' -s 'config.uuidLDAPAttribute=["entryUUID"]' -s 'config.userObjectClasses=["inetOrgPerson, organizationalPerson"]' -s 'config.connectionUrl=["ldap://#:10389"]'  -s 'config.usersDn=["ou=People,dc=keycloak,dc=org"]' -s 'config.authType=["simple"]' -s 'config.bindDn=["uid=admin,ou=system"]' -s 'config.bindCredential=["secret"]' -s 'config.searchScope=["1"]' -s 'config.useTruststoreSpi=["always"]' -s 'config.connectionPooling=["true"]' -s 'config.pagination=["true"]' -s 'config.allowKerberosAuthentication=["true"]' -s 'config.serverPrincipal=["HTTP/localhost@KEYCLOAK.ORG"]' -s 'config.keyTab=["http.keytab"]' -s 'config.kerberosRealm=["KEYCLOAK.ORG"]' -s 'config.debug=["true"]' -s 'config.useKerberosForPasswordAuthentication=["true"]'

移除用户存储提供程序实例

  1. 使用存储提供程序实例的 id 属性来组成端点 URI,例如 components/ID

  2. 对此端点运行 delete 命令。

    例如

    $ kcadm.sh delete components/3d9c572b-8f33-483f-98a6-8bb421667867 -r demorealm

触发特定用户存储提供程序的所有用户同步

  1. 使用存储提供程序的 id 属性来组成端点 URI,例如 user-storage/ID_OF_USER_STORAGE_INSTANCE/sync

  2. 添加 action=triggerFullSync 查询参数。

  3. 运行 create 命令。

    例如

    $ kcadm.sh create user-storage/b7c63d02-b62a-4fc1-977c-947d6a09e1ea/sync?action=triggerFullSync

触发特定用户存储提供程序的已更改用户同步

  1. 使用存储提供程序的 id 属性来组成端点 URI,例如 user-storage/ID_OF_USER_STORAGE_INSTANCE/sync

  2. 添加 action=triggerChangedUsersSync 查询参数。

  3. 运行 create 命令。

    例如

    $ kcadm.sh create user-storage/b7c63d02-b62a-4fc1-977c-947d6a09e1ea/sync?action=triggerChangedUsersSync

测试 LDAP 用户存储连接性

  1. testLDAPConnection 端点上运行 get 命令。

  2. 提供查询参数 bindCredentialbindDnconnectionUrluseTruststoreSpi

  3. action 查询参数设置为 testConnection

    例如

    $ kcadm.sh create testLDAPConnection -s action=testConnection -s bindCredential=secret -s bindDn=uid=admin,ou=system -s connectionUrl=ldap://#:10389 -s useTruststoreSpi=always

测试 LDAP 用户存储身份验证

  1. testLDAPConnection 端点上运行 get 命令。

  2. 提供查询参数 bindCredentialbindDnconnectionUrluseTruststoreSpi

  3. action 查询参数设置为 testAuthentication

    例如

    $ kcadm.sh create testLDAPConnection -s action=testAuthentication -s bindCredential=secret -s bindDn=uid=admin,ou=system -s connectionUrl=ldap://#:10389 -s useTruststoreSpi=always

添加映射器

添加硬编码角色 LDAP 映射器

  1. components 端点上运行 create 命令。

  2. providerType 属性设置为 org.keycloak.storage.ldap.mappers.LDAPStorageMapper

  3. parentId 属性设置为 LDAP 提供程序实例的 ID。

  4. providerId 属性设置为 hardcoded-ldap-role-mapper。确保您提供 role 配置参数的值。

    例如

    $ kcadm.sh create components -r demorealm -s name=hardcoded-ldap-role-mapper -s providerId=hardcoded-ldap-role-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config.role=["realm-management.create-client"]'

添加 MS 活动目录 映射器

  1. components 端点上运行 create 命令。

  2. providerType 属性设置为 org.keycloak.storage.ldap.mappers.LDAPStorageMapper

  3. parentId 属性设置为 LDAP 提供程序实例的 ID。

  4. providerId 属性设置为 msad-user-account-control-mapper

    例如

    $ kcadm.sh create components -r demorealm -s name=msad-user-account-control-mapper -s providerId=msad-user-account-control-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea

添加用户属性 LDAP 映射器

  1. components 端点上运行 create 命令。

  2. providerType 属性设置为 org.keycloak.storage.ldap.mappers.LDAPStorageMapper

  3. parentId 属性设置为 LDAP 提供程序实例的 ID。

  4. providerId 属性设置为 user-attribute-ldap-mapper

    例如

    $ kcadm.sh create components -r demorealm -s name=user-attribute-ldap-mapper -s providerId=user-attribute-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."user.model.attribute"=["email"]' -s 'config."ldap.attribute"=["mail"]' -s 'config."read.only"=["false"]' -s 'config."always.read.value.from.ldap"=["false"]' -s 'config."is.mandatory.in.ldap"=["false"]'

添加组 LDAP 映射器

  1. components 端点上运行 create 命令。

  2. providerType 属性设置为 org.keycloak.storage.ldap.mappers.LDAPStorageMapper

  3. parentId 属性设置为 LDAP 提供程序实例的 ID。

  4. providerId 属性设置为 group-ldap-mapper

    例如

    $ kcadm.sh create components -r demorealm -s name=group-ldap-mapper -s providerId=group-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."groups.dn"=[]' -s 'config."group.name.ldap.attribute"=["cn"]' -s 'config."group.object.classes"=["groupOfNames"]' -s 'config."preserve.group.inheritance"=["true"]' -s 'config."membership.ldap.attribute"=["member"]' -s 'config."membership.attribute.type"=["DN"]' -s 'config."groups.ldap.filter"=[]' -s 'config.mode=["LDAP_ONLY"]' -s 'config."user.roles.retrieve.strategy"=["LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"]' -s 'config."mapped.group.attributes"=["admins-group"]' -s 'config."drop.non.existing.groups.during.sync"=["false"]' -s 'config.roles=["admins"]' -s 'config.groups=["admins-group"]' -s 'config.group=[]' -s 'config.preserve=["true"]' -s 'config.membership=["member"]'

添加全名 LDAP 映射器

  1. components 端点上运行 create 命令。

  2. providerType 属性设置为 org.keycloak.storage.ldap.mappers.LDAPStorageMapper

  3. parentId 属性设置为 LDAP 提供程序实例的 ID。

  4. providerId 属性设置为 full-name-ldap-mapper

    例如

    $ kcadm.sh create components -r demorealm -s name=full-name-ldap-mapper -s providerId=full-name-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."ldap.full.name.attribute"=["cn"]' -s 'config."read.only"=["false"]' -s 'config."write.only"=["true"]'

身份验证操作

设置密码策略

  1. 将域的 passwordPolicy 属性设置为一个枚举表达式,该表达式包含特定的策略提供程序 ID 和可选配置。

  2. 使用以下示例将密码策略设置为默认值。默认值包括

    • 210,000 次哈希迭代

    • 至少一个特殊字符

    • 至少一个大写字符

    • 至少一个数字字符

    • 不得等于用户的 username

    • 至少八个字符长

      $ kcadm.sh update realms/demorealm -s 'passwordPolicy="hashIterations and specialChars and upperCase and digits and notUsername and length"'
  3. 要使用与默认值不同的值,请在括号中传递配置。

  4. 使用以下示例将密码策略设置为

    • 300,000 次哈希迭代

    • 至少两个特殊字符

    • 至少两个大写字符

    • 至少两个小写字符

    • 至少两个数字

    • 至少九个字符长

    • 不得等于用户的 username

    • 至少四个更改后不重复

      $ kcadm.sh update realms/demorealm -s 'passwordPolicy="hashIterations(300000) and specialChars(2) and upperCase(2) and lowerCase(2) and digits(2) and length(9) and notUsername and passwordHistory(4)"'

获取当前密码策略

您可以通过过滤除 passwordPolicy 属性之外的所有输出来获取当前域配置。

例如,显示 demorealmpasswordPolicy

$ kcadm.sh get realms/demorealm --fields passwordPolicy

列出身份验证流程

authentication/flows 端点上运行 get 命令。

例如

$ kcadm.sh get authentication/flows -r demorealm

获取特定的身份验证流程

authentication/flows/FLOW_ID 端点上运行 get 命令。

例如

$ kcadm.sh get authentication/flows/febfd772-e1a1-42fb-b8ae-00c0566fafb8 -r demorealm

列出流程的执行

authentication/flows/FLOW_ALIAS/executions 端点上运行 get 命令。

例如

$ kcadm.sh get authentication/flows/Copy%20of%20browser/executions -r demorealm

向执行添加配置

  1. 获取流程的执行。

  2. 记下流程的 ID。

  3. authentication/executions/{executionId}/config 端点上运行 create 命令。

例如

$ kcadm.sh create "authentication/executions/a3147129-c402-4760-86d9-3f2345e401c7/config" -r demorealm -b '{"config":{"x509-cert-auth.mapping-source-selection":"Match SubjectDN using regular expression","x509-cert-auth.regular-expression":"(.*?)(?:$)","x509-cert-auth.mapper-selection":"Custom Attribute Mapper","x509-cert-auth.mapper-selection.user-attribute-name":"usercertificate","x509-cert-auth.crl-checking-enabled":"","x509-cert-auth.crldp-checking-enabled":false,"x509-cert-auth.crl-relative-path":"crl.pem","x509-cert-auth.ocsp-checking-enabled":"","x509-cert-auth.ocsp-responder-uri":"","x509-cert-auth.keyusage":"","x509-cert-auth.extendedkeyusage":"","x509-cert-auth.confirmation-page-disallowed":""},"alias":"my_otp_config"}'

获取执行的配置

  1. 获取流程的执行。

  2. 记下其 authenticationConfig 属性,其中包含配置 ID。

  3. authentication/config/ID 端点上运行 get 命令。

例如

$ kcadm get "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r demorealm

更新执行的配置

  1. 获取流程的执行。

  2. 获取流程的 authenticationConfig 属性。

  3. 从属性中记下配置 ID。

  4. authentication/config/ID 端点上运行 update 命令。

例如

$ kcadm update "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r demorealm -b '{"id":"dd91611a-d25c-421a-87e2-227c18421833","alias":"my_otp_config","config":{"x509-cert-auth.extendedkeyusage":"","x509-cert-auth.mapper-selection.user-attribute-name":"usercertificate","x509-cert-auth.ocsp-responder-uri":"","x509-cert-auth.regular-expression":"(.*?)(?:$)","x509-cert-auth.crl-checking-enabled":"true","x509-cert-auth.confirmation-page-disallowed":"","x509-cert-auth.keyusage":"","x509-cert-auth.mapper-selection":"Custom Attribute Mapper","x509-cert-auth.crl-relative-path":"crl.pem","x509-cert-auth.crldp-checking-enabled":"false","x509-cert-auth.mapping-source-selection":"Match SubjectDN using regular expression","x509-cert-auth.ocsp-checking-enabled":""}}'

删除执行的配置

  1. 获取流程的执行。

  2. 获取流程的 authenticationConfig 属性。

  3. 从属性中记下配置 ID。

  4. authentication/config/ID 端点上运行 delete 命令。

例如

$ kcadm delete "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r demorealm