From 4a0ca9ff3bc6c4b794a7ce0bf35b57e7fde444e8 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 11 May 2024 00:05:58 +0200 Subject: [PATCH] add frontchannel-logout.ftl page --- src/bin/keycloakify/generateFtl/pageId.ts | 3 +- src/login/Fallback.tsx | 3 ++ src/login/Template.tsx | 3 +- src/login/TemplateProps.ts | 1 + src/login/kcContext/KcContext.ts | 14 +++++++- src/login/kcContext/kcContextMocks.ts | 17 ++++++++++ src/login/pages/FrontchannelLogout.tsx | 41 +++++++++++++++++++++++ 7 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/login/pages/FrontchannelLogout.tsx diff --git a/src/bin/keycloakify/generateFtl/pageId.ts b/src/bin/keycloakify/generateFtl/pageId.ts index 679a19e5..94a336ff 100644 --- a/src/bin/keycloakify/generateFtl/pageId.ts +++ b/src/bin/keycloakify/generateFtl/pageId.ts @@ -28,7 +28,8 @@ export const loginThemePageIds = [ "saml-post-form.ftl", "delete-credential.ftl", "code.ftl", - "delete-account-confirm.ftl" + "delete-account-confirm.ftl", + "frontchannel-logout.ftl" ] as const; export const accountThemePageIds = ["password.ftl", "account.ftl", "sessions.ftl", "totp.ftl", "applications.ftl", "log.ftl"] as const; diff --git a/src/login/Fallback.tsx b/src/login/Fallback.tsx index 6510d3da..85177fea 100644 --- a/src/login/Fallback.tsx +++ b/src/login/Fallback.tsx @@ -34,6 +34,7 @@ const SamlPostForm = lazy(() => import("keycloakify/login/pages/SamlPostForm")); const DeleteCredential = lazy(() => import("keycloakify/login/pages/DeleteCredential")); const Code = lazy(() => import("keycloakify/login/pages/Code")); const DeleteAccountConfirm = lazy(() => import("keycloakify/login/pages/DeleteAccountConfirm")); +const FrontchannelLogout = lazy(() => import("keycloakify/login/pages/FrontchannelLogout")); type FallbackProps = PageProps & { UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>; @@ -104,6 +105,8 @@ export default function Fallback(props: FallbackProps) { return ; case "delete-account-confirm.ftl": return ; + case "frontchannel-logout.ftl": + return ; } assert>(false); })()} diff --git a/src/login/Template.tsx b/src/login/Template.tsx index 04acf097..d5e84144 100644 --- a/src/login/Template.tsx +++ b/src/login/Template.tsx @@ -21,6 +21,7 @@ export default function Template(props: TemplateProps) { showUsernameNode = null, socialProvidersNode = null, infoNode = null, + documentTitle, kcContext, i18n, doUseDefaultCss, @@ -35,7 +36,7 @@ export default function Template(props: TemplateProps) { const { realm, locale, auth, url, message, isAppInitiatedAction, authenticationSession, scripts } = kcContext; useEffect(() => { - document.title = msgStr("loginTitle", kcContext.realm.displayName); + document.title = documentTitle ?? msgStr("loginTitle", kcContext.realm.displayName); }, []); useSetClassName({ diff --git a/src/login/TemplateProps.ts b/src/login/TemplateProps.ts index 723e6313..82cc9128 100644 --- a/src/login/TemplateProps.ts +++ b/src/login/TemplateProps.ts @@ -16,6 +16,7 @@ export type TemplateProps(); @@ -514,6 +515,17 @@ export declare namespace KcContext { pageId: "delete-account-confirm.ftl"; triggered_from_aia: boolean; }; + + export type FrontchannelLogout = Common & { + pageId: "frontchannel-logout.ftl"; + logout: { + clients: { + name: string; + frontChannelLogoutUrl: string; + }[]; + logoutRedirectUri?: string; + }; + }; } export type UserProfile = { diff --git a/src/login/kcContext/kcContextMocks.ts b/src/login/kcContext/kcContextMocks.ts index bd6c89c3..19ae426a 100644 --- a/src/login/kcContext/kcContextMocks.ts +++ b/src/login/kcContext/kcContextMocks.ts @@ -678,6 +678,23 @@ export const kcContextMocks = [ id({ ...kcContextCommonMock, pageId: "login-page-expired.ftl" + }), + + id({ + ...kcContextCommonMock, + pageId: "frontchannel-logout.ftl", + "logout": { + "clients": [ + { + "name": "myApp", + "frontChannelLogoutUrl": "#" + }, + { + "name": "myApp2", + "frontChannelLogoutUrl": "#" + } + ] + } }) ]; diff --git a/src/login/pages/FrontchannelLogout.tsx b/src/login/pages/FrontchannelLogout.tsx new file mode 100644 index 00000000..c9c1e208 --- /dev/null +++ b/src/login/pages/FrontchannelLogout.tsx @@ -0,0 +1,41 @@ +import { useEffect } from "react"; +import type { PageProps } from "keycloakify/login/pages/PageProps"; +import type { KcContext } from "../kcContext"; +import type { I18n } from "../i18n"; + +export default function FrontchannelLogout(props: PageProps, I18n>) { + const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; + + const { logout } = kcContext; + + const { msg, msgStr } = i18n; + + useEffect(() => { + if (logout.logoutRedirectUri) { + window.location.replace(logout.logoutRedirectUri); + } + }, []); + + return ( +