使用 Keycloak SSO 在 2 个应用程序之间保持身份验证
Posted
技术标签:
【中文标题】使用 Keycloak SSO 在 2 个应用程序之间保持身份验证【英文标题】:Keep authentication between 2 applications with Keycloak SSO 【发布时间】:2019-05-19 06:27:10 【问题描述】:我有 2 个 JHipster 应用程序在一个子域(app1.domain.tld 和 app2.domain.tld)上运行。
在这两个应用程序中,用户都通过 Keycloak 登录。顺序是这样的:
-
Angular 应用向 Keycloak 发送带有凭据的 /authenticate 请求
如果响应成功,则返回身份验证 cookie
POST 请求被发送到生成 JSessionID cookie 的 Jhipster 后端应用程序
JSessionID 然后用于对支持的应用程序的每个请求。
如果用户已经登录域 (*.domain.tld) 的其中一个应用程序,那么自动登录用户(无需询问用户名和密码)的最佳方式是什么?
我尝试将 JSessionID 用作全局令牌,然后才明白它仅适用于生成它的应用程序...
也许捕获 Keycloak 身份验证 cookie(在第 2 步返回)并在第二个应用程序上进行身份验证可以解决问题?
根据我在测试时看到的情况,在第一个应用程序上通过身份验证后,当我转到第二个应用程序时,Angular 401 HTTP 拦截器会重定向到带有会话令牌的 keycloak 登录页面。因此,那时 Keycloak 应该会看到我已经登录并且应该将我重定向到我的第二个应用程序的主页。
我说的对吗?
【问题讨论】:
有什么解决办法吗?我也有同样的要求。 【参考方案1】:javascript adapter 通过创建从身份验证服务器加载的 iframe 来解决此问题。
来自keycloak docs:
会话状态 iframe
默认情况下,JavaScript 适配器会创建一个隐藏的 iframe,用于检测是否发生了单点注销。这不需要任何网络流量,而是通过查看特殊状态 cookie 来检索状态。可以通过在传递给 init 方法的选项中设置 checkLoginIframe: false 来禁用此功能。您不应依赖于直接查看此 cookie。它的格式可以改变,并且它还与 Keycloak 服务器的 URL 相关联,而不是您的应用程序。
init函数的成功回调有一个参数,给出用户的认证状态。
<script src="keycloak.js"></script>
<script>
var keycloak = Keycloak();
keycloak.init().success(function(authenticated)
alert(authenticated ? 'authenticated' : 'not authenticated');
).error(function()
alert('failed to initialize');
);
</script>
如果用户通过身份验证,则将用户重定向到登录页面,因为用户已经通过身份验证,因此无需再次输入登录凭据。如果使用 onload 选项 check-sso
进行初始化,适配器可以自动处理此问题
有关javascript适配器内部工作原理的更多详细信息,可以找到源代码here
【讨论】:
感谢您的回答,但在我的情况下似乎不起作用。问题似乎出在 jHipster 和 Keycloak 之间,因为当我生成 2 个标准 JHipster 应用程序并将它们连接到我的 keycloak 实例时,一次只能连接 1 个应用程序。当我连接到另一个应用程序时,第一个应用程序断开连接 您是否对两个应用程序使用相同的客户端? “断开连接”是什么意思? @Biologeek 是的,我为这两个应用程序使用了相同的 clientId 和 clientSecret。两者都在 Spring application.yml 中设置。我所说的断开连接的意思是,当我回到登录的第一个应用程序时,在连接到第二个应用程序后,对后端的 REST 调用导致第一个应用程序出现 401 HTTP 错误。 我建议configure 不同的 客户端为keycloak 中的每个应用程序。 两个不同的 clientId 和 clientSecret 的结果相同...似乎在同一领域中每个用户只允许一个连接以上是关于使用 Keycloak SSO 在 2 个应用程序之间保持身份验证的主要内容,如果未能解决你的问题,请参考以下文章
Keycloak Realm VS Keycloak 客户端
使用 Keycloak 和 Azure Active Directory 的 SSO
Keycloak:获取当前 SSO 会话的 UserSessionModel