返回

Keycloak SAML单点登出(SLO)难题与解决之道

php

SAML会话校验及单点登出(SLO)难题:Keycloak 作为身份提供商(IDP)的挑战

使用SAML进行单点登录(SSO)时,一个常见的问题是单点登出(SLO)的实现,特别是当身份提供商(IDP)为 Keycloak 时。 简单来说,问题在于当用户在一个应用程序中注销后,其他依赖于同一 Keycloak IDP 认证的应用程序仍然保持登录状态。 这样的行为有潜在的安全隐患。 深入研究,我们能够理解其中的根本原因以及解决方案。

理解SAML会话及单点登出的原理

SAML协议并非直接提供持续的会话验证,它主要依赖于初始的认证断言,并在应用本地设置会话,通常通过cookie实现。 单点登录通过共享认证状态工作。当用户第一次访问一个应用并由 Keycloak 验证通过后,应用程序将建立本地会话。后续用户访问同一IDP验证的另一应用程序时,无需重复验证。 而问题在于:当用户从某个应用程序登出时,这种登出行为并非自动同步到其他应用及 Keycloak IDP 本身。这就是单点登出的关键挑战。

理论上,SAML应该实现一个全面的单点登出机制,当用户从任一应用登出时,IDP 及所有依赖该IDP的应用程序的会话也随之失效。 但这依赖于所有参与者的正确配合。 Keycloak 在默认配置下不提供对所有 SLO 方法(如 backchannel logout)的支持,从而引发会话失效问题。 常见的PHP SAML实现往往依赖于cookie过期时间来控制会话有效期,而不是与IDP实时校验。 这在单点登出场景中,并不能实现真正的会话失效。

针对 Keycloak 的 SLO 问题及解决方案

要解决 Keycloak 和 PHP 应用 SLO 的挑战,需采取以下几种方法:

1. 减少会话有效期

一种简单的方法是减少应用程序会话 cookie 的有效期。 这确保会话不会长期存在,从而降低因会话保持未失效产生的风险。 此方法并不能实现真正的单点登出,它更像一种妥协。 但它可以减少会话过期时间较长的窗口期,从而降低攻击的风险。

示例代码(修改 config.php 配置文件中与会话相关的设置):

    'session.cookie.lifetime' => 86400, //设置 cookie 生命周期为 1 天(秒)
    'session.rememberme.lifetime' => 604800, //记住我 cookie的生命周期设置为 7 天(秒)

操作步骤:

  1. 找到并编辑应用程序中的 config.php 文件。
  2. 修改 session.cookie.lifetime 的值为较小的时间。
  3. 修改 session.rememberme.lifetime,以便”记住我”功能的有效期符合实际需求。
  4. 保存修改并测试应用程序会话超时表现。

安全建议: 务必将 Cookie 的 httpOnlysecure 属性设置为 true, 确保只有 HTTP 请求才可以访问该 Cookie,且Cookie只能通过 HTTPS 连接传输。

2. 使用 SAML 客户端库支持的 SLO 方法

某些 PHP SAML 工具包支持 HTTP 重定向方式的单点登出。 但如果 Keycloak 默认没有启用后端 SLO,这样的方法作用会非常有限。

示例代码 (使用 php-saml 库发起 SLO):

<?php
require_once 'vendor/autoload.php';
use OneLogin\Saml2\Auth;

$settings = [
    // SAML 设置...
];

$auth = new Auth($settings);
$auth->logout(null, $auth->getNameId(), null, true);

操作步骤:

  1. 使用 Composer 安装 php-saml 包。
  2. 根据需要配置 SAML 设置,包括 IDP 元数据和本地实体配置。
  3. 调用 $auth->logout() 函数,该函数会尝试发起 SLO 请求。
  4. 注意 $auth->logout() 方法的 localLogout 参数,此参数指定了在返回IDP执行SLO之前,是否应该清除本地session。

说明: 该方法依赖于 IDP 支持。对于 Keycloak 默认配置而言,SLO 会由 Keycloak 重定向处理。 但是,并不能实现所有的单点登出行为。

3. 后端 Channel SLO (需要 Keycloak 支持)

Keycloak 可通过 SOAP Binding 提供 backchannel logout 支持,虽然其实现可能并不直接,并需要特别配置。 一旦启用 backchannel logout,当用户在某一个应用登出时,将有一个服务与Keycloak进行交互,随后通知所有关联应用注销当前用户的 session。此方案可以更加有效的实现全面的单点登出,提升安全性和一致性。

Keycloak 后端配置 (简化步骤):

  1. 确认您的 Keycloak 版本是否支持后端 SLO。
  2. 配置您的 Keycloak realm 以支持 backchannel logout(请参考 Keycloak 文档了解详细步骤,涉及 client 配置及 backchannel SLO 支持配置)。
  3. 配置客户端 SAML 绑定方式和 backchannel 相关的服务URL。
  4. 在 SAML 客户端的配置中,将注销请求设置为发送到 Keycloak 的后通道 SLO 端点。

** PHP 应用适配:**

需要配置SAML客户端,以便使用相应的 Binding,将注销请求以 backchannel SLO 的方式发送至 Keycloak。 部分工具包提供该项配置选项。

** 操作步骤:**

  1. 详读并按 Keycloak 版本文档,完成上述配置。
  2. 修改客户端配置,启用相应的配置项。
  3. 根据 SAML 工具包的使用方式配置参数,以使用后通道 SLO。

** 说明:** 这是一个更为复杂和高级的实现方式, 涉及到Keycloak的深度配置和 SAML 库的相应能力,但该方法理论上可以实现最理想的单点登出体验。

结论

通过了解SAML 单点登出的原理以及 Keycloak 作为IDP的特点,我们可以使用合适的策略应对挑战。 简单来说,减少会话时长是应对 SLO 的基本方案,而使用 HTTP 重定向或 backchannel SLO (如果 Keycloak 配置支持)能提供更完整的单点登出体验。选择哪种策略需要根据具体的安全需求、应用复杂度和IDP的能力来确定。 更重要的是要时刻关注相关工具及协议规范的更新。 实施真正的 SLO 往往需要在多方间协同进行,这不仅涉及应用的正确配置,还需要 IDP 提供相应的支持。 请务必采取合适的配置,增强应用安全性。