第 10 章 SSO 协议
本节讨论红帽构建的 Keycloak 身份验证服务器,以及由红帽构建的 Keycloak 身份验证服务器保护应用程序的方式,并与这些协议进行交互。
10.1. 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 服务根据令牌中的访问信息决定处理或拒绝请求。
10.1.1. OIDC 身份验证流
OIDC 有几个方法或流,客户端或应用程序可用于验证用户并接收 身份和 访问令牌。该方法取决于请求访问的应用或客户端的类型。
10.1.1.1. 授权代码流
授权代码流是基于浏览器的协议,它适合验证和授权基于浏览器的应用程序。它使用浏览器重定向来获取 身份和 访问令牌。
- 用户使用浏览器连接至应用程序。应用程序检测到用户没有登录到应用程序。
- 应用程序将浏览器重定向到红帽构建的 Keycloak 进行验证。
- 应用在浏览器重定向中作为查询参数传递回调 URL。红帽构建的 Keycloak 在身份验证成功后使用该参数。
- 红帽构建的 Keycloak 验证用户,并创建一个一次性、短期的临时代码。
- Red Hat build of Keycloak 使用回调 URL 重定向到应用程序,并在回调 URL 中添加临时代码作为查询参数。
- 应用程序提取临时代码,并对红帽构建的 Keycloak 发出后台 REST 调用,以交换 身份和 访问和 刷新令牌 的代码。为防止重播攻击,临时代码不能多次使用。
在令牌生命周期中,系统容易受到 stolen 令牌的影响。出于安全性和可扩展性的原因,访问令牌通常被设置为快速过期,因此后续令牌请求会失败。如果令牌过期,应用程序可以使用登录协议发送的额外 刷新令牌 来获取新的访问令牌。
机密 客户端在为令牌交换临时代码时提供客户端机密。不需要 公共 客户端来提供客户端 secret。当 HTTPS 被严格强制执行并重定向为客户端注册的 URI 时,公共 客户端是安全的。HTML5/JavaScript 客户端必须是 公共 客户端,因为无法安全地将客户端 secret 传送到 HTML5/JavaScript 客户端。如需了解更多详细信息,请参阅管理客户端 章节。
红帽构建的 Keycloak 还支持代码 交换规范的概念验证。
10.1.1.2. 隐式流
Implicit Flow 是一个基于浏览器的协议。它与授权代码流类似,但请求较少且没有刷新令牌。
当令牌通过重定向 URI 传输令牌时,在浏览器历史记录中可能存在访问令牌泄漏的情况(请参阅以下)。
另外,此流不会为客户端提供刷新令牌。因此,访问令牌必须长期存在,或者用户在过期时重新验证。
我们不推荐使用这个流。这个流被支持,因为它在 OIDC 和 OAuth 2.0 规格中。
协议按如下方式工作:
- 用户使用浏览器连接至应用程序。应用程序检测到用户没有登录到应用程序。
- 应用程序将浏览器重定向到红帽构建的 Keycloak 进行验证。
- 应用在浏览器重定向中作为查询参数传递回调 URL。红帽构建的 Keycloak 在成功身份验证时使用查询参数。
- 红帽构建的 Keycloak 验证用户,并创建一个 身份和 访问令牌。Red Hat build of Keycloak 使用回调 URL 重定向到应用程序,并额外在回调 URL 中添加 身份和 访问令牌 作为查询参数。
- 应用从回调 URL 提取 身份和 访问令牌。
10.1.1.3. 资源所有者密码凭证授权(直接访问授予)
REST 客户端使用 直接访问授予 代表用户获取令牌。这是一个 HTTP POST 请求,其中包含:
- 用户的凭据。凭据以表单参数发送。
- 客户端的 id。
- 客户端 secret (如果它是机密客户端)。
HTTP 响应包含 身份、访问和 刷新令牌。
10.1.1.4. 客户端凭证授权
客户端凭证授予 根据与客户端关联的服务帐户的元数据和权限创建一个令牌,而不是获取代表外部用户的令牌。REST 客户端使用客户端凭证授予。
如需更多信息,请参阅服务帐户章节。???
10.1.2. 刷新令牌授权
默认情况下,红帽构建的 Keycloak 在令牌响应中返回刷新令牌。一些例外是隐式流或客户端凭证授予上述。
刷新令牌与 SSO 浏览器会话的用户会话关联,并在用户会话的生命周期内有效。但是,该客户端应为每个指定间隔至少发送一次 refresh-token 请求。否则,会话可以被视为"idle",并可过期。如需更多信息,请参阅 超时部分。
Red Hat build of Keycloak 支持 离线令牌,在客户端需要使用刷新令牌时,即使对应的浏览器 SSO 会话已经过期,也可以使用它。
10.1.2.1. 刷新令牌轮转
可以指定刷新令牌在被使用后被视为无效。这意味着,客户端必须始终从最后一次刷新响应保存刷新令牌,因为已经使用的旧刷新令牌,红帽构建的 Keycloak 不再被视为有效。这可以通过使用 Revoke Refresh token 选项设置,如 timeout 部分中指定的。???
红帽构建的 Keycloak 还支持没有刷新令牌轮转的情况。在这种情况下,在登录期间返回刷新令牌,但刷新令牌请求的后续响应不会返回新的刷新令牌。建议在 FAPI 2 草案规格中 为实例提供这种方法。在红帽构建的 Keycloak 中,可以使用 客户端策略 跳过刷新令牌轮转。您可以将 executor suppress-refresh-token-rotation
添加到某些客户端配置集,并将客户端策略配置为触发配置集,这意味着将跳过刷新令牌轮转的客户端。
10.1.2.2. 设备授权
这供运行在有有限输入功能的互联网连接设备或缺少合适的浏览器的客户端使用。以下是协议的简短概述:
- 应用程序请求红帽构建 Keycloak,一个设备代码和用户代码。红帽构建的 Keycloak 创建一个设备代码和用户代码。红帽构建的 Keycloak 会向应用程序返回包括设备代码和用户代码的响应。
- 应用为用户提供代码和验证 URI。用户使用另一个浏览器访问验证 URI 进行验证。您可以定义一个简短的 validation_uri,它将重定向到代理中的 Keycloak 验证 URI (/realms/realm_name/device)外 Keycloak - fe。
- 应用程序会重复轮询红帽构建的 Keycloak,以查找用户是否已完成用户授权。如果用户身份验证已完成,应用会交换 身份 的设备代码,访问和 刷新令牌。
10.1.2.3. 客户端启动后通道身份验证授权
此功能供希望通过直接与 OpenID 提供程序通信的客户端使用,而无需通过 OAuth 2.0 的授权代码授权代码授权代码等用户浏览器重定向。以下是协议的简短概述:
- 客户端请求红帽构建的 Keycloak 是一个 auth_req_id,用于标识客户端发出的身份验证请求。红帽构建的 Keycloak 创建 auth_req_id。
- 收到这个 auth_req_id 后,此客户端会重复轮询红帽构建的 Keycloak,以获取来自红帽构建的 Keycloak 的访问令牌、刷新令牌和 ID 令牌,以返回 auth_req_id,直到用户被验证为止。
管理员可以将 Client Initiated Backchannel Authentication (CIBA)相关操作配置为 每个域的 CIBA 策略
。
另请参阅,请参阅红帽构建的 Keycloak 文档的其他位置,如保护应用程序和服务指南的 back channel Authentication Endpoint 部分,以及保护应用程序和服务指南的 Client Initiated Backchannel Authentication Grant 部分。
10.1.2.3.1. CIBA 策略
管理员在 管理控制台
上执行以下操作:
-
打开
Authentication
选项卡。CIBA Policy -
配置项目并点
Save
。
可配置的项目及其描述如下。
Configuration | 描述 |
---|---|
Backchannel Token Delivery 模式 | 指定 CD (辅助设备)如何获取身份验证结果和相关令牌。有三种模式:"poll"、"ping" 和 "push"。红帽构建的 Keycloak 只支持 "poll"。默认设置为 "poll"。这个配置是必需的。如需了解更多详细信息,请参阅 CIBA 规格。 |
过期时间 | 从收到身份验证请求以来,"auth_req_id"的过期时间(以秒为单位)。默认设置为 120。这个配置是必需的。如需了解更多详细信息,请参阅 CIBA 规格。 |
Interval(间隔) | CD (持续设备)在轮询请求到令牌端点之间需要等待的时间(以秒为单位)。默认设置为 5。这个配置是可选的。如需了解更多详细信息,请参阅 CIBA 规格。 |
身份验证请求的用户提示 | 识别要请求身份验证的最终用户的方法。默认设置为 "login_hint"。有三种模式:"login_hint", "login_hint_token" 和 "id_token_hint"。红帽构建的 Keycloak 只支持 "login_hint"。这个配置是必需的。如需了解更多详细信息,请参阅 CIBA 规格。 |
10.1.2.3.2. 供应商设置
CIBA 授权使用以下两个供应商。
- 身份验证频道供应商 :提供红帽构建的 Keycloak 和实际通过 AD (身份验证设备)验证用户的实体之间的通信。
-
用户 Resolver Provider:从客户端提供的信息获取红帽构建的 Keycloak
UserModel
,以识别用户。
红帽构建的 Keycloak 具有这两个默认供应商。但是,管理员需要设置 Authentication Channel 供应商,如下所示:
kc.[sh|bat] start --spi-ciba-auth-channel-ciba-http-auth-channel-http-authentication-channel-uri=https://backend.internal.example.com
可配置的项目及其描述如下。
Configuration | 描述 |
---|---|
http-authentication-channel-uri | 指定实际通过 AD 验证用户的实体的 URI (身份验证设备)。 |
10.1.2.3.3. 身份验证频道供应商
CIBA 标准文档没有指定如何通过 AD 验证用户。因此,它可能会由产品自由裁量实施。红帽构建的 Keycloak 将这个身份验证委托给外部身份验证实体。为了与身份验证实体通信,红帽构建的 Keycloak 提供身份验证频道提供程序。
其红帽构建的 Keycloak 实施假定身份验证实体由红帽构建的 Keycloak 控制下,以便红帽构建的 Keycloak 信任身份验证实体。不建议使用红帽构建的 Keycloak 无法控制的身份验证实体。
身份验证频道提供程序作为 SPI 供应商提供,以便红帽构建的 Keycloak 用户可以实施自己的供应商,以满足其环境。红帽构建的 Keycloak 提供名为 HTTP Authentication Channel Provider 的默认供应商,该提供程序使用 HTTP 与身份验证实体通信。
如果红帽构建的 Keycloak 用户希望使用 HTTP Authentication Channel Provider,则需要知道红帽构建的 Keycloak 和由以下两个部分组成的身份验证实体之间的合同。
- 身份验证委派请求/响应
- 红帽构建的 Keycloak 将身份验证请求发送到身份验证实体。
- 身份验证结果通知/ACK
- 身份验证实体会通知红帽构建的 Keycloak 身份验证的结果。
身份验证委派请求/响应由以下消息组成:
- 身份验证委托请求
- 该请求从红帽构建的 Keycloak 发送到身份验证实体,以要求它供 AD 进行身份验证。
POST [delegation_reception]
- Headers
Name | 值 | 描述 |
---|---|---|
Content-Type | application/json | 消息正文是 json 格式。 |
授权 | bearer [token] | 当身份验证实体通知红帽构建的 Keycloak 身份验证结果时,会使用 [token]。 |
- 参数
类型 | Name | 描述 |
---|---|---|
路径 | delegation_reception | 身份验证实体提供用于接收委派请求的端点 |
- Body
Name | 描述 |
---|---|
login_hint |
它告知 AD 身份验证的身份验证实体。 |
scope |
它告知身份验证实体从经过身份验证的用户获得许可的范围。 |
is_consent_required |
它显示了身份验证实体是否需要从经过身份验证的用户获得有关范围的许可。 |
binding_message |
其值应该在 CD 和 AD UI 中显示,以便用户识别 AD 的身份验证是由 CD 触发的。 |
acr_values |
它告知从 CD 请求身份验证上下文类参考。 |
- 身份验证委派响应
响应从身份验证实体返回到红帽构建的 Keycloak,以通知身份验证实体从红帽构建的 Keycloak 收到身份验证请求。
- 响应
HTTP 状态代码 | 描述 |
---|---|
201 | 它通知红帽构建的 Keycloak 接收身份验证委托请求。 |
身份验证结果通知/ACK 由以下消息组成:
- 身份验证结果通知
- 身份验证实体向红帽构建的 Keycloak 发送身份验证请求的结果。
POST /realms/[realm]/protocol/openid-connect/ext/ciba/auth/callback
- Headers
Name | 值 | 描述 |
---|---|---|
Content-Type | application/json | 消息正文是 json 格式。 |
授权 | bearer [token] | [token] 必须是身份验证实体在 Authentication Delegation Request 中从红帽构建的 Keycloak 接收的身份验证实体。 |
- 参数
类型 | Name | 描述 |
---|---|---|
路径 | realm | realm 名称 |
- Body
Name | 描述 |
---|---|
status |
它告知 AD 进行用户身份验证的结果。 |
- 身份验证结果 ACK
从红帽构建的 Keycloak 返回响应到身份验证实体,以通知红帽构建的 Keycloak 收到来自身份验证实体的 AD 进行用户身份验证的结果。
- 响应
HTTP 状态代码 | 描述 |
---|---|
200 | 它通知身份验证实体接收身份验证结果的通知。 |
10.1.2.3.4. 用户 Resolver 供应商
即使同一用户,其表示可能在每个 CD 中有所不同,Red Hat build of Keycloak 和身份验证实体也是如此。
对于 CD,红帽构建的 Keycloak 和身份验证实体用于识别同一用户,此用户 Resolver 提供程序会转换他们自己的用户表示形式。
用户 Resolver 提供程序作为 SPI 供应商提供,以便红帽构建的 Keycloak 用户可以实施自己的供应商来满足其环境。红帽构建的 Keycloak 提供名为 Default User Resolver Provider 的默认供应商,它具有以下特征:
-
只支持
login_hint
参数,并用作默认参数。 -
红帽构建的 Keycloak 中的 UserModel
用户名
用于代表 CD 上的用户、红帽构建的 Keycloak 和身份验证实体。
10.1.3. OIDC Logout
OIDC 有四个与注销机制相关的规格:
由于所有这些操作在 OIDC 规范中进行了描述,我们将在此处提供简短概述。
10.1.3.1. 会话管理
这是一个基于浏览器的注销。应用程序定期从红帽构建的 Keycloak 获取会话状态信息。当会话在红帽构建的 Keycloak 时终止时,应用程序会注意到并触发其自身的注销。
10.1.3.2. RP-Initiated Logout
这也是基于浏览器的注销,退出开始将用户重定向到红帽构建的 Keycloak 上的特定端点。当用户点击一些应用程序页面中的 Log Out
链接时,通常会发生这个重定向,之前使用 Red Hat build of Keycloak 来验证用户。
用户重定向到 logout 端点后,红帽构建的 Keycloak 将向客户端发送注销请求,从而使他们在本地用户会话无效,并在注销过程完成后可能会将用户重定向到一些 URL。当用户没有使用 id_token_hint
参数时,可能会有选择要求确认注销。注销后,只要它作为参数提供,用户会自动重定向到指定的 post_logout_redirect_uri
。请注意,如果包含 post_logout_redirect_uri
,则需要包含 client_id
或 id_token_hint
参数。另外,post_logout_redirect_uri
参数需要匹配客户端 配置中指定的 Valid Post Logout Redirect URI
之一。
根据客户端配置,可以通过前端频道或通过后端通道将注销请求发送到客户端。对于依赖于上一节中描述的会话管理前端浏览器客户端,红帽构建的 Keycloak 不需要向它们发送任何注销请求;这些客户端会自动检测浏览器中的 SSO 会话。
10.1.3.3. front-channel Logout
要将客户端配置为通过前端通道接收登出请求,请查看 Front-Channel Logout 客户端设置。使用此方法时,请考虑以下几点:
-
注销由红帽构建的 Keycloak 发送到客户端的请求依赖浏览器,并在为注销页面呈现的嵌入式
iframes
。 -
根据
iframes
,前端通道注销可能会受到内容安全策略(CSP)的影响,注销请求可能会阻止。 - 如果用户在呈现注销页面之前关闭浏览器,或者在实际向客户端发送出出请求之前,客户端中的会话可能无法无效。
考虑使用 Back-Channel Logout,因为它提供了一种更加可靠和安全的方法来注销用户并在客户端上终止其会话。
如果没有通过前端注销启用客户端,则红帽构建的 Keycloak 将首先尝试使用 Back-Channel Logout URL 通过 back-channel 发送注销请求。如果没有定义,服务器将回退到使用 Admin URL。
10.1.3.4. Backchannel Logout
这是一个基于非浏览器的注销,它使用红帽构建的 Keycloak 和客户端之间的直接后备通道通信。Red Hat build of Keycloak 发送 HTTP POST 请求,其中包含一个注销令牌到登录到红帽构建的 Keycloak 的所有客户端。这些请求在 Red Hat build of Keycloak 中发送到注册的 backchannel logout URL,应该会在客户端触发注销。
10.1.4. 红帽构建的 Keycloak 服务器 OIDC URI 端点
以下是红帽构建的 Keycloak 发布的 OIDC 端点列表。当非红帽构建的 Keycloak 客户端适配器使用 OIDC 与身份验证服务器通信时,可以使用这些端点。它们都是相对 URL。URL 的根由 HTTP (S)协议、主机名和可选的路径组成:例如,
https://localhost:8080
- /realms/{realm-name}/protocol/openid-connect/auth
- 用于在授权代码流中获取临时代码,或使用 Implicit Flow、Direct Grants 或 Client Grants 获取令牌。
- /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
- 用于 OAuth 2.0 令牌撤销,如 RFC7009 中所述。
- /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
- 这是 Client Initiated Backchannel Authentication Grant 的 URL 端点,以获取用于标识客户端发出的身份验证请求的 auth_req_id。
- /realms/{realm-name}/protocol/openid-connect/logout/backchannel-logout
- 这是执行 OIDC 规格中描述的后端注销的 URL 端点。
在所有系统中,将 {realm-name} 替换为域的名称。