Many organizations have a requirement that when a new user logs in for the first time, they need to agree to the terms and conditions of the website.
First you need to enable the required action on the Keycloak server admin console:\
Then you load your own terms in Markdown format like this:
login/KcApp.tsx
import { lazy, Suspense } from"react";import Fallback, { type PageProps } from"keycloakify/login";importtype { KcContext } from"./kcContext";import { useI18n } from"./i18n";import { useDownloadTerms } from"keycloakify/login";import tos_en_url from"./assets/tos_en.md";import tos_fr_url from"./assets/tos_fr.md";constDefaultTemplate=lazy(() =>import("keycloakify/login/Template"));exportdefaultfunctionApp(props: { kcContext:KcContext; }) {const { kcContext } = props;consti18n=useI18n({ kcContext });useDownloadTerms({ kcContext,"downloadTermMarkdown":async ({ currentLanguageTag }) => {consttos_url= (() => {switch (currentLanguageTag) {case"fr": return tos_fr_url;default: return tos_en_url; } })();if ("__STORYBOOK_ADDONS"in window) {// NOTE: In storybook, when you import a .md file you get the content of the file.// In Create React App on the other hand you get an url to the file.return tos_url; }constmarkdownString=awaitfetch(tos_url).then(response =>response.text());return markdownString; } });if (i18n ===null) {//NOTE: Locales not yet downloaded, we could as well display a loading progress but it's usually a matter of milliseconds.returnnull; }return ( <Suspense> {(() => {switch (kcContext.pageId) {default: return <Fallback {...{ kcContext, i18n }} Template={DefaultTemplate} doUseDefaultCss />; } })()} </Suspense> );}
You can also eject the terms.ftl page if you're not happy with the default look:
Nice to know: You can access user infos and attribute in the Terms page. This enables you to display different terms depending on what option the user selected on the registration page: