Keycloak - 弹出窗口中的外部 IDP
Keycloak - external IDPs in Pop Up
我在 iframe 中使用 keycloak。
在我的 keycloak 后面是一些二级 IDP,比如 google 和 facebook。
使用我当前的配置,keycloak 只是重定向到那些辅助 IDP。这意味着它们也在 iframe 中打开。
我真的很想改变它,因为它与我的一些主要安全策略相矛盾。
我能以某种方式告诉 keycloak 在弹出窗口中打开外部 IDP 吗?
我已经阅读了 keycloak "server administration guide" 但找不到任何关于此问题的信息。
好的,我找到了一个涉及大量 js hack 的解决方法。
1.
我将登录主题的 login.ftl 更改为不仅仅是社交提供商的 href,而是执行一些 js。
所以在此之前:
<a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}">
现在是这样的:
<a onclick="openInPopUp('${p.loginUrl}', '${name}')" id="zocial-${p.alias}" class="zocial ${p.providerId}">
<form id="kc_social_continue" method="post">
</form>
<script>
function openInPopUp(url, name) {
let popup = window.open(url, name, 'toolbar=no,width=600,height=600');
let receiveMessage = (event) => {
if (event.origin !== (window.location.protocol + '//' + window.location.hostname)){
return;
}
document.forms['kc_social_continue'].action = event.data;
document.forms['kc_social_continue'].submit();
};
window.addEventListener('message', receiveMessage, false);
}
</script>
它的作用是在弹出窗口中打开身份提供者。
此外,注册了一个消息侦听器,它期望 URL 作为消息正文。每当收到消息时,都会将一个空表单发布到相应的 URL.
2.
添加自定义身份验证 SPI。这只是向用户展示了一个自定义的自由标记模板。
public class ClosePopupAuthenticator implements Authenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
Response challenge = context.form().createForm("close-popup.ftl");
context.challenge(challenge);
}
@Override
public void action(AuthenticationFlowContext context) {
context.success();
}
}
这个 close-popup.ftl 将它的 loginAction-URL 发送给父级 window 然后自己关闭。
<script>
let host = window.location.hostname;
let protocol = window.location.protocol;
window.opener.postMessage("${url.loginAction}", protocol + '//' + host);
window.close();
</script>
3.
将此新 SPI 添加到新流程并将此流程设置为所有相关身份提供商的 "Post Login Flow"。
我在 iframe 中使用 keycloak。 在我的 keycloak 后面是一些二级 IDP,比如 google 和 facebook。
使用我当前的配置,keycloak 只是重定向到那些辅助 IDP。这意味着它们也在 iframe 中打开。 我真的很想改变它,因为它与我的一些主要安全策略相矛盾。
我能以某种方式告诉 keycloak 在弹出窗口中打开外部 IDP 吗? 我已经阅读了 keycloak "server administration guide" 但找不到任何关于此问题的信息。
好的,我找到了一个涉及大量 js hack 的解决方法。
1.
我将登录主题的 login.ftl 更改为不仅仅是社交提供商的 href,而是执行一些 js。 所以在此之前:
<a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}">
现在是这样的:
<a onclick="openInPopUp('${p.loginUrl}', '${name}')" id="zocial-${p.alias}" class="zocial ${p.providerId}">
<form id="kc_social_continue" method="post">
</form>
<script>
function openInPopUp(url, name) {
let popup = window.open(url, name, 'toolbar=no,width=600,height=600');
let receiveMessage = (event) => {
if (event.origin !== (window.location.protocol + '//' + window.location.hostname)){
return;
}
document.forms['kc_social_continue'].action = event.data;
document.forms['kc_social_continue'].submit();
};
window.addEventListener('message', receiveMessage, false);
}
</script>
它的作用是在弹出窗口中打开身份提供者。
此外,注册了一个消息侦听器,它期望 URL 作为消息正文。每当收到消息时,都会将一个空表单发布到相应的 URL.
2.
添加自定义身份验证 SPI。这只是向用户展示了一个自定义的自由标记模板。
public class ClosePopupAuthenticator implements Authenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
Response challenge = context.form().createForm("close-popup.ftl");
context.challenge(challenge);
}
@Override
public void action(AuthenticationFlowContext context) {
context.success();
}
}
这个 close-popup.ftl 将它的 loginAction-URL 发送给父级 window 然后自己关闭。
<script>
let host = window.location.hostname;
let protocol = window.location.protocol;
window.opener.postMessage("${url.loginAction}", protocol + '//' + host);
window.close();
</script>
3.
将此新 SPI 添加到新流程并将此流程设置为所有相关身份提供商的 "Post Login Flow"。