From 11f71c91020348c8266c2fa30ee4de0e9e03fb95 Mon Sep 17 00:00:00 2001 From: Abel Aoun Date: Wed, 26 Jul 2023 15:35:54 +0200 Subject: [PATCH 01/23] Update .gitignore - yarn cache dir Yarn produce many files when running yarn install. According to their doc[1], most of the files should be ignored, unless a zero-install strategy is wanted (which ois not the case here AFAIK). [1] https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored --- .gitignore | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7c5d5ec..f96d6f1 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,16 @@ jspm_packages # Optional npm cache directory .npm +# yarn cache directory +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + + # Optional REPL history .node_repl_history @@ -44,4 +54,4 @@ jspm_packages /build_keycloak /build -/storybook-static \ No newline at end of file +/storybook-static From 0f469a1da13e060cf3b18652f6df11f9a82dc752 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Fri, 22 Sep 2023 16:02:19 +0200 Subject: [PATCH 02/23] Update Keycloakify --- package.json | 2 +- src/keycloak-theme/account/Template.tsx | 2 +- src/keycloak-theme/login/Template.tsx | 2 +- yarn.lock | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f858c0f..da85b77 100755 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "evt": "^2.4.15", "jwt-decode": "^3.1.2", "keycloak-js": "^21.0.1", - "keycloakify": "8.0.0-rc.2", + "keycloakify": "^8.1.0", "powerhooks": "^0.26.8", "react": "18.1.0", "react-dom": "18.1.0", diff --git a/src/keycloak-theme/account/Template.tsx b/src/keycloak-theme/account/Template.tsx index 0c33a05..7f8236a 100644 --- a/src/keycloak-theme/account/Template.tsx +++ b/src/keycloak-theme/account/Template.tsx @@ -24,7 +24,7 @@ export default function Template(props: TemplateProps) { `${url.resourcesCommonPath}/node_modules/patternfly/dist/css/patternfly-additions.min.css`, `${url.resourcesPath}/css/account.css` ], - "htmlClassName": undefined, + "htmlClassName": getClassName("kcHtmlClass"), "bodyClassName": clsx("admin-console", "user", getClassName("kcBodyClass")) }); diff --git a/src/keycloak-theme/login/Template.tsx b/src/keycloak-theme/login/Template.tsx index 3b60e09..871bca1 100644 --- a/src/keycloak-theme/login/Template.tsx +++ b/src/keycloak-theme/login/Template.tsx @@ -40,7 +40,7 @@ export default function Template(props: TemplateProps) { `${url.resourcesPath}/css/login.css` ], "htmlClassName": getClassName("kcHtmlClass"), - "bodyClassName": undefined + "bodyClassName": getClassName("kcBodyClass") }); if (!isReady) { diff --git a/yarn.lock b/yarn.lock index 0b55aa1..a98cf24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9768,10 +9768,10 @@ keycloak-js@^21.0.1: base64-js "^1.5.1" js-sha256 "^0.9.0" -keycloakify@8.0.0-rc.2: - version "8.0.0-rc.2" - resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.0.0-rc.2.tgz#748c16b538c89f8b2be9d309dea98d5fb4c8ada7" - integrity sha512-W9ImhiXCHGW8i1KP8zb5MZ0Ug1imro1mKsos8QBbFci51sDLrKM/ymmpsvkm+5mmXAjh4mVgBAn4mspvizo1WQ== +keycloakify@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.0.tgz#f2d1fb7144cda7bf5d8a539183e3e3a69405728c" + integrity sha512-BU6Y/2X+6iKUK12TvWMds9zgALxMtLOpFphZWrc6LLwqdieF6XE0QTPTN9UeTEXdgOLOcgNLuGx4csBjZ9WDPw== dependencies: "@babel/generator" "^7.22.9" "@babel/parser" "^7.22.7" From cf5f5054a63ddde4b4d0150b23805220c3ff79e5 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Fri, 22 Sep 2023 16:02:31 +0200 Subject: [PATCH 03/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da85b77..024d76c 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.7.0", + "version": "4.7.1", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From 27cb236f0f093ad6f6c11ae9c6b41f8b6b281d0f Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Mon, 2 Oct 2023 23:08:58 +0200 Subject: [PATCH 04/23] Update keycloakify --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 024d76c..1586105 100755 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "evt": "^2.4.15", "jwt-decode": "^3.1.2", "keycloak-js": "^21.0.1", - "keycloakify": "^8.1.0", + "keycloakify": "^8.1.2", "powerhooks": "^0.26.8", "react": "18.1.0", "react-dom": "18.1.0", diff --git a/yarn.lock b/yarn.lock index a98cf24..6c0d1de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9768,10 +9768,10 @@ keycloak-js@^21.0.1: base64-js "^1.5.1" js-sha256 "^0.9.0" -keycloakify@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.0.tgz#f2d1fb7144cda7bf5d8a539183e3e3a69405728c" - integrity sha512-BU6Y/2X+6iKUK12TvWMds9zgALxMtLOpFphZWrc6LLwqdieF6XE0QTPTN9UeTEXdgOLOcgNLuGx4csBjZ9WDPw== +keycloakify@^8.1.2: + version "8.1.2" + resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.2.tgz#ecd8e07980bed17d2a585455c704fbc198657fe6" + integrity sha512-JKhwPJndmC5tADW4+XcxoYb3dyQClvO6HGS1szt3iFfmppYEHi/PFyQ4I4cpFzLL/IvQMR4beufDJkni3xYRyA== dependencies: "@babel/generator" "^7.22.9" "@babel/parser" "^7.22.7" From 324cda026ecb9415319f5433bb85bfb1f1323cdd Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Mon, 2 Oct 2023 23:09:11 +0200 Subject: [PATCH 05/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1586105..76c6467 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.7.1", + "version": "4.7.2", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From 1dfc9ed68c467f6bd76d99632e9be415f1ca70d0 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Mon, 9 Oct 2023 04:08:27 +0200 Subject: [PATCH 06/23] Update keycloakify --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 76c6467..5913358 100755 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "evt": "^2.4.15", "jwt-decode": "^3.1.2", "keycloak-js": "^21.0.1", - "keycloakify": "^8.1.2", + "keycloakify": "^8.1.3", "powerhooks": "^0.26.8", "react": "18.1.0", "react-dom": "18.1.0", diff --git a/yarn.lock b/yarn.lock index 6c0d1de..981f31d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9768,10 +9768,10 @@ keycloak-js@^21.0.1: base64-js "^1.5.1" js-sha256 "^0.9.0" -keycloakify@^8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.2.tgz#ecd8e07980bed17d2a585455c704fbc198657fe6" - integrity sha512-JKhwPJndmC5tADW4+XcxoYb3dyQClvO6HGS1szt3iFfmppYEHi/PFyQ4I4cpFzLL/IvQMR4beufDJkni3xYRyA== +keycloakify@^8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.3.tgz#813836b013dc93d5cf43a5b476c9f19537e5435c" + integrity sha512-KdAvtqslWNggqtLAgWmPkWxiOK/tfkbxTJUmQw5DGXig1NNpdm39WRRtg9MjLnAlwsRfWw/uOdvlBR95x/5g3g== dependencies: "@babel/generator" "^7.22.9" "@babel/parser" "^7.22.7" From be386fd8ac814e6873c172db70ad24dcc55ce131 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Mon, 9 Oct 2023 04:08:40 +0200 Subject: [PATCH 07/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5913358..c3969c3 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.7.2", + "version": "4.7.3", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From ab4b205980561bcfbee398554d170f8b285ac222 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 22 Oct 2023 12:39:00 +0200 Subject: [PATCH 08/23] Migrate from keycloak-js to oidc-spa --- README.md | 2 +- package.json | 3 +- src/App/App.tsx | 180 ++++++++++----- src/App/oidc.tsx | 213 ------------------ src/keycloak-theme/login/KcApp.tsx | 4 - src/keycloak-theme/login/pages/Login.tsx | 25 +- .../login/valuesTransferredOverUrl.ts | 123 ---------- yarn.lock | 42 ++-- 8 files changed, 170 insertions(+), 422 deletions(-) delete mode 100644 src/App/oidc.tsx delete mode 100644 src/keycloak-theme/login/valuesTransferredOverUrl.ts diff --git a/README.md b/README.md index 60ed840..8b8cf65 100644 --- a/README.md +++ b/README.md @@ -220,4 +220,4 @@ jobs: EOF ``` -You can also remove `jwt-decode`, `keycloak-js`, `powerhooks` and `tsafe` from your dependencies. +You can also remove `oidc-spa`, `powerhooks` and `tsafe` from your dependencies. diff --git a/package.json b/package.json index c3969c3..2419387 100755 --- a/package.json +++ b/package.json @@ -27,8 +27,7 @@ "keywords": [], "dependencies": { "evt": "^2.4.15", - "jwt-decode": "^3.1.2", - "keycloak-js": "^21.0.1", + "oidc-spa": "^1.0.1", "keycloakify": "^8.1.3", "powerhooks": "^0.26.8", "react": "18.1.0", diff --git a/src/App/App.tsx b/src/App/App.tsx index b6146dc..8fd8a10 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -1,86 +1,69 @@ import "./App.css"; import logo from "./logo.svg"; import myimg from "./myimg.png"; -import { createOidcClientProvider, useOidcClient } from "./oidc"; -import { addFooToQueryParams, addBarToQueryParams } from "../keycloak-theme/login/valuesTransferredOverUrl"; -import jwt_decode from "jwt-decode"; -import { addParamToUrl } from "powerhooks/tools/urlSearchParams"; +import { useMemo } from "react"; +import { createOidcProvider, useOidc } from "oidc-spa/react"; +import { addQueryParamToUrl } from "oidc-spa/tools/urlQueryParams"; +import { decodeJwt } from "oidc-spa"; +import { assert } from "tsafe/assert"; //On older Keycloak version you need the /auth (e.g: http://localhost:8080/auth) //On newer version you must remove it (e.g: http://localhost:8080 ) const keycloakUrl = "https://auth.code.gouv.fr/auth"; const keycloakRealm = "keycloakify"; -const keycloakClient= "starter"; +const keycloakClientId= "starter"; -const { OidcClientProvider } = createOidcClientProvider({ - url: keycloakUrl, - realm: keycloakRealm, - clientId: keycloakClient, - //This function will be called just before redirecting, - //it should return the current langue. - //kcContext.locale.currentLanguageTag will be what this function returned just before redirecting. - getUiLocales: () => "en", - transformUrlBeforeRedirect: url => - [url] - //Instead of foo and bar you could have isDark for example or any other state that you wish to - //transfer from the main app to the login pages. - .map(url => addFooToQueryParams({ url, value: { foo: 42 } })) - .map(url => addBarToQueryParams({ url, value: "value of bar transferred to login page" })) - [0], - log: console.log +const { OidcProvider } = createOidcProvider({ + issuerUri: `${keycloakUrl}/realms/${keycloakRealm}`, + clientId: keycloakClientId, + transformUrlBeforeRedirect: url => { + + // This adding ui_locales to the url will ensure the consistency of the language between the app and the login pages + // If your app implements a i18n system (like i18nifty.dev for example) you should use this and replace "en" by the + // current language of the app. + // On the other side you will find kcContext.locale.currentLanguageTag to be whatever you set here. + url = addQueryParamToUrl({ + url, + "name": "ui_locales", + "value": "en", + }).newUrl; + + // If you want to pass some custom state to the login pages... + // See in src/keycloak-theme/pages/Login.tsx how it's retrieved. + url = addQueryParamToUrl({ + url, + "name": "my_custom_param", + "value": "value of foo transferred to login page", + }).newUrl; + + return url; + + }, + // Uncomment if your app is not hosted at the origin and update /foo/bar/baz. + //silentSsoUrl: `${window.location.origin}/foo/bar/baz/silent-sso.html`, }); export default function App() { return ( - + - + ); } + function ContextualizedApp() { - const { oidcClient } = useOidcClient(); - - let accountUrl = `${keycloakUrl}/realms/${keycloakRealm}/account`; - - // Set the language the user will get on the account page - accountUrl = addParamToUrl({ - url: accountUrl, - name: "kc_locale", - value: "en" - }).newUrl; - - // Enable to redirect to the app from the account page we'll get the referrer_uri under kcContext.referrer.url - // It's useful to avoid hard coding the app url in the keycloak config - accountUrl = addParamToUrl({ - url: accountUrl, - name: "referrer", - value: keycloakClient - }).newUrl; - - accountUrl = addParamToUrl({ - url: accountUrl, - name: "referrer_uri", - value: window.location.href - }).newUrl; + const { oidc } = useOidc(); return (
{ - oidcClient.isUserLoggedIn ? - <> -

You are authenticated !

- {/* On older Keycloak version its /auth/realms instead of /realms */} - Link to your Keycloak account -
{JSON.stringify(jwt_decode(oidcClient.getAccessToken()), null, 2)}
- - + oidc.isUserLoggedIn ? + oidc.logout({ redirectTo: "home" })} /> : - <> - - + } logo test_image @@ -90,4 +73,85 @@ function ContextualizedApp() {
); + +} + +function AuthenticatedRoute(props: { logout: () => void; }) { + + const { logout } = props; + + const { user } = useUser(); + + return ( + <> +

Hello {user.name} !

+ Link to your Keycloak account + +
{JSON.stringify(user, null, 2)}
+ + ); + +} + +function useUser() { + const { oidc } = useOidc(); + + assert(oidc.isUserLoggedIn, "This hook can only be used when the user is logged in"); + + const { idToken } = oidc.getTokens(); + + const user = useMemo( + () => + decodeJwt<{ + // Use https://jwt.io/ to tell what's in your idToken + // It will depend of your Keycloak configuration. + // Here I declare only two field on the type but actually there are + // Many more things available. + sub: string; + name: string; + preferred_username: string; + // This is a custom attribute set up in our Keycloak configuration + // it's not present by default. + // See https://docs.keycloakify.dev/realtime-input-validation#getting-your-custom-user-attribute-to-be-included-in-the-jwt + favorite_pet: "cat" | "dog" | "bird"; + }>(idToken), + [idToken] + ); + + return { user }; +} + +function buildAccountUrl( + params: { + locale: string; + } +){ + + const { locale } = params; + + let accountUrl = `${keycloakUrl}/realms/${keycloakRealm}/account`; + + // Set the language the user will get on the account page + accountUrl = addQueryParamToUrl({ + url: accountUrl, + name: "kc_locale", + value: locale + }).newUrl; + + // Enable to redirect to the app from the account page we'll get the referrer_uri under kcContext.referrer.url + // It's useful to avoid hard coding the app url in the keycloak config + accountUrl = addQueryParamToUrl({ + url: accountUrl, + name: "referrer", + value: keycloakClientId + }).newUrl; + + accountUrl = addQueryParamToUrl({ + url: accountUrl, + name: "referrer_uri", + value: window.location.href + }).newUrl; + + return accountUrl; + } diff --git a/src/App/oidc.tsx b/src/App/oidc.tsx deleted file mode 100644 index 44eb9e1..0000000 --- a/src/App/oidc.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { useState, useContext, createContext, useEffect } from "react"; -import Keycloak_js from "keycloak-js"; -import { id } from "tsafe/id"; -import { addParamToUrl } from "powerhooks/tools/urlSearchParams"; -import type { ReturnType } from "tsafe/ReturnType"; -import type { Param0 } from "tsafe/Param0"; -import { assert } from "tsafe/assert"; -import { createKeycloakAdapter } from "keycloakify"; -import jwt_decode from "jwt-decode"; -import { Evt } from "evt"; - -export declare type OidcClient = OidcClient.LoggedIn | OidcClient.NotLoggedIn; - -export declare namespace OidcClient { - export type NotLoggedIn = { - isUserLoggedIn: false; - login: (params: { - //To prevent infinite loop if the user access a page that requires to - //be authenticated but cancel (clicks back). - doesCurrentHrefRequiresAuth: boolean; - }) => Promise; - }; - - export type LoggedIn = { - isUserLoggedIn: true; - getAccessToken: () => string; - logout: (params: { redirectTo: "home" | "current page" }) => Promise; - //If we have sent a API request to change user's email for example - //and we want that jwt_decode(oidcClient.getAccessToken()).email be the new email - //in this case we would call this method... - updateTokenInfos: () => Promise; - }; -} - -type Params = { - url: string; - realm: string; - clientId: string; - transformUrlBeforeRedirect?: (url: string) => string; - getUiLocales?: () => string; - log?: typeof console.log; -}; - -async function createKeycloakOidcClient(params: Params): Promise { - const { - url, - realm, - clientId, - transformUrlBeforeRedirect, - getUiLocales, - log - } = params; - - const keycloakInstance = new Keycloak_js({ url, realm, clientId }); - - let redirectMethod: ReturnType< - Param0["getRedirectMethod"] - > = "overwrite location.href"; - - const isAuthenticated = await keycloakInstance - .init({ - onLoad: "check-sso", - silentCheckSsoRedirectUri: `${window.location.origin}/silent-sso.html`, - responseMode: "query", - checkLoginIframe: false, - adapter: createKeycloakAdapter({ - transformUrlBeforeRedirect: url => - [url] - .map(transformUrlBeforeRedirect ?? (url => url)) - .map( - getUiLocales === undefined ? - (url => url) : - url => - addParamToUrl({ - url, - "name": "ui_locales", - "value": getUiLocales() - }).newUrl - ) - [0], - keycloakInstance, - getRedirectMethod: () => redirectMethod - }) - }) - .catch((error: Error) => error); - - //TODO: Make sure that result is always an object. - if (isAuthenticated instanceof Error) { - throw isAuthenticated; - } - - const login: OidcClient.NotLoggedIn["login"] = async ({ - doesCurrentHrefRequiresAuth - }) => { - if (doesCurrentHrefRequiresAuth) { - redirectMethod = "location.replace"; - } - - await keycloakInstance.login({ "redirectUri": window.location.href }); - - return new Promise(() => { }); - }; - - if (!isAuthenticated) { - return id({ - "isUserLoggedIn": false, - login - }); - } - - let currentAccessToken = keycloakInstance.token!; - - const oidcClient = id({ - "isUserLoggedIn": true, - "getAccessToken": () => currentAccessToken, - "logout": async ({ redirectTo }) => { - await keycloakInstance.logout({ - "redirectUri": (() => { - switch (redirectTo) { - case "current page": - return window.location.href; - case "home": - return window.location.origin; - } - })() - }); - - return new Promise(() => { }); - }, - "updateTokenInfos": async () => { - await keycloakInstance.updateToken(-1); - - currentAccessToken = keycloakInstance.token!; - } - }); - - (function callee() { - const msBeforeExpiration = jwt_decode<{ exp: number }>(currentAccessToken)["exp"] * 1000 - Date.now(); - - setTimeout(async () => { - - log?.(`OIDC access token will expire in ${minValiditySecond} seconds, waiting for user activity before renewing`); - - await Evt.merge([ - Evt.from(document, "mousemove"), - Evt.from(document, "keydown") - ]).waitFor(); - - log?.("User activity detected. Refreshing access token now"); - - const error = await keycloakInstance.updateToken(-1).then( - () => undefined, - (error: Error) => error - ); - - if (error) { - log?.("Can't refresh OIDC access token, getting a new one"); - //NOTE: Never resolves - await login({ "doesCurrentHrefRequiresAuth": true }); - } - - currentAccessToken = keycloakInstance.token!; - - callee(); - - }, msBeforeExpiration - minValiditySecond * 1000); - })(); - - return oidcClient; -} - -const minValiditySecond = 25; - -const oidcClientContext = createContext(undefined); - -export function createOidcClientProvider(params: Params) { - - - const prOidcClient = createKeycloakOidcClient(params); - - function OidcClientProvider(props: { children: React.ReactNode; }) { - - const { children } = props; - - const [oidcClient, setOidcClient] = useState(undefined); - - useEffect(() => { - - prOidcClient.then(setOidcClient); - - }, []); - - if (oidcClient === undefined) { - return null; - } - - return ( - - {children} - - ); - - } - - return { OidcClientProvider }; - -} - -export function useOidcClient() { - const oidcClient = useContext(oidcClientContext); - assert(oidcClient !== undefined); - return { oidcClient }; -} diff --git a/src/keycloak-theme/login/KcApp.tsx b/src/keycloak-theme/login/KcApp.tsx index 120ec1d..683a7c2 100644 --- a/src/keycloak-theme/login/KcApp.tsx +++ b/src/keycloak-theme/login/KcApp.tsx @@ -7,10 +7,6 @@ import { useI18n } from "./i18n"; const Template = lazy(() => import("./Template")); const DefaultTemplate = lazy(() => import("keycloakify/login/Template")); -// You can uncomment this to see the values passed by the main app before redirecting. -//import { foo, bar } from "./valuesTransferredOverUrl"; -//console.log(`Values passed by the main app in the URL parameter:`, { foo, bar }); - const Login = lazy(() => import("./pages/Login")); // If you can, favor register-user-profile.ftl over register.ftl, see: https://docs.keycloakify.dev/realtime-input-validation const Register = lazy(() => import("./pages/Register")); diff --git a/src/keycloak-theme/login/pages/Login.tsx b/src/keycloak-theme/login/pages/Login.tsx index 1de3f27..abc250b 100644 --- a/src/keycloak-theme/login/pages/Login.tsx +++ b/src/keycloak-theme/login/pages/Login.tsx @@ -5,6 +5,17 @@ import type { PageProps } from "keycloakify/login/pages/PageProps"; import { useGetClassName } from "keycloakify/login/lib/useGetClassName"; import type { KcContext } from "../kcContext"; import type { I18n } from "../i18n"; +import { retrieveQueryParamFromUrl } from "oidc-spa/tools/urlQueryParams"; + +const result = retrieveQueryParamFromUrl({ + "url": window.location.href, + "name": "my_custom_param", +}); + +if (result.wasPresent) { + console.log("my_custom_param", result.value); +} + export default function Login(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; @@ -60,7 +71,7 @@ export default function Login(props: PageProps {realm.password && ( @@ -71,8 +82,8 @@ export default function Login(props: PageProps {msg("rememberMe")} @@ -149,8 +160,8 @@ export default function Login(props: PageProps { - const queryParamName = "foo"; - - type Type = { foo: number; }; - - const value = (()=> { - - const unparsedValue = read({ queryParamName }); - - if( unparsedValue === undefined ){ - return undefined; - } - - return JSON.parse(unparsedValue) as Type; - - })(); - - function addToUrlQueryParams(params: { - url: string; - value: Type; - }): string { - const { url, value } = params; - - return addParamToUrl({ - url, - "name": queryParamName, - "value": JSON.stringify(value) - }).newUrl; - } - - const out = { - [queryParamName]: value, - [`add${capitalize(queryParamName)}ToQueryParams` as const]: addToUrlQueryParams - } as const; - - return out; -})(); - -export const { bar, addBarToQueryParams } = (() => { - const queryParamName = "bar"; - - type Type = string; - - const value = (()=> { - - const unparsedValue = read({ queryParamName }); - - if( unparsedValue === undefined ){ - return undefined; - } - - return JSON.parse(unparsedValue) as Type; - - })(); - - function addToUrlQueryParams(params: { - url: string; - value: Type; - }): string { - const { url, value } = params; - - return addParamToUrl({ - url, - "name": queryParamName, - "value": JSON.stringify(value) - }).newUrl; - } - - const out = { - [queryParamName]: value, - [`add${capitalize(queryParamName)}ToQueryParams` as const]: addToUrlQueryParams - } as const; - - return out; -})(); - - -function read(params: { queryParamName: string }): string | undefined { - if (kcContext === undefined || process.env.NODE_ENV !== "production") { - //NOTE: We do something only if we are really in Keycloak - return undefined; - } - - const { queryParamName } = params; - - read_from_url: { - const result = retrieveParamFromUrl({ - "url": window.location.href, - "name": queryParamName - }); - - if (!result.wasPresent) { - break read_from_url; - } - - const { newUrl, value: serializedValue } = result; - - updateSearchBarUrl(newUrl); - - localStorage.setItem(queryParamName, serializedValue); - - return serializedValue; - } - - //Reading from local storage - const serializedValue = localStorage.getItem(queryParamName); - - if (serializedValue === null) { - throw new Error( - `Missing ${queryParamName} in URL when redirecting to login page` - ); - } - - return serializedValue; -} diff --git a/yarn.lock b/yarn.lock index 981f31d..9324bc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4706,7 +4706,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2, base64-js@^1.5.1: +base64-js@^1.0.2: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -5801,6 +5801,11 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -9613,11 +9618,6 @@ js-sdsl@^4.1.4: resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== -js-sha256@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" - integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== - js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -9760,14 +9760,6 @@ jwt-decode@^3.1.2: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== -keycloak-js@^21.0.1: - version "21.0.2" - resolved "https://registry.yarnpkg.com/keycloak-js/-/keycloak-js-21.0.2.tgz#1d3c2079d3c23850df4f253a868926861c51c488" - integrity sha512-i05i3VBPhQ867EgjA+OYPlf8YUPiUwtrU2zv4j8tvZIdRvhJY8f+mp1ZvRJl/GMRb+XhJs9BDknyBMrIspwDkw== - dependencies: - base64-js "^1.5.1" - js-sha256 "^0.9.0" - keycloakify@^8.1.3: version "8.1.3" resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.3.tgz#813836b013dc93d5cf43a5b476c9f19537e5435c" @@ -10917,6 +10909,23 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +oidc-client-ts@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-2.3.0.tgz#43c90f1f0cc3be2e4ede38b8c68642ba00bfa8f6" + integrity sha512-7RUKU+TJFQo+4X9R50IGJAIDF18uRBaFXyZn4VVCfwmwbSUhKcdDnw4zgeut3uEXkiD3NqURq+d88sDPxjf1FA== + dependencies: + crypto-js "^4.1.1" + jwt-decode "^3.1.2" + +oidc-spa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-1.0.0.tgz#f050722af4820ba30e94ec326ed7b35e4085170d" + integrity sha512-8m8tibYq5yTM5taLPBu4fuy1muCMwZWna/f/xxRbfC+DbA8pcwLH/fPI4F3GQ3AqQcnmJdFPhTkmZHX3YA5NiQ== + dependencies: + jwt-decode "^3.1.2" + oidc-client-ts "^2.3.0" + tsafe "^1.6.5" + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -14294,6 +14303,11 @@ tsafe@^1.6.0: resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.0.tgz#48a9bd0a4c43df43d289bdfc1d89f0d7fffbd612" integrity sha512-wlUeRBnyN3EN2chXznpLm7vBEvJLEOziDU+MN6NRlD99AkwmXgtChNQhp+V97VyRa3Bp05IaL4Cocsc7JlyEUg== +tsafe@^1.6.5: + version "1.6.5" + resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.5.tgz#74943b69190069168a53d2accd6d07891cf1cce8" + integrity sha512-895zss8xqqHKTc28sHGIfZKnt3C5jrstB1DyPr/h3/flK0zojsZUMQL1/W4ytdDW6KI4Oth62nb9rrxmA3s3Iw== + tsconfig-paths@^3.14.1: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" From 83d587805fea40c977c5e71b81e1edca91596f9c Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 22 Oct 2023 12:39:25 +0200 Subject: [PATCH 09/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2419387..6d1822f 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.7.3", + "version": "4.8.0", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From fc26fe2f052b750b6ccc089fef060c5db54c8dbb Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 22 Oct 2023 12:48:16 +0200 Subject: [PATCH 10/23] Update lockfile --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9324bc3..bf2170d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10917,10 +10917,10 @@ oidc-client-ts@^2.3.0: crypto-js "^4.1.1" jwt-decode "^3.1.2" -oidc-spa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-1.0.0.tgz#f050722af4820ba30e94ec326ed7b35e4085170d" - integrity sha512-8m8tibYq5yTM5taLPBu4fuy1muCMwZWna/f/xxRbfC+DbA8pcwLH/fPI4F3GQ3AqQcnmJdFPhTkmZHX3YA5NiQ== +oidc-spa@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-1.0.1.tgz#205a7613def6b7aea9b4c2ad71e952180f8c3dcb" + integrity sha512-vrd0peFSSHphVNEvS1s76ZR21fQr1tPBuwQLK6MyReMN9r9HA+BfDOFEiYs1Q9nixrecMQVDQsF7nBxQfwSscA== dependencies: jwt-decode "^3.1.2" oidc-client-ts "^2.3.0" From 82fede2f7fb385c779771b8fe483845e0c839d1f Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 22 Oct 2023 16:22:35 +0200 Subject: [PATCH 11/23] Update keycloakify --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6d1822f..ef71e7e 100755 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dependencies": { "evt": "^2.4.15", "oidc-spa": "^1.0.1", - "keycloakify": "^8.1.3", + "keycloakify": "^8.2.1", "powerhooks": "^0.26.8", "react": "18.1.0", "react-dom": "18.1.0", diff --git a/yarn.lock b/yarn.lock index bf2170d..0747665 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9760,10 +9760,10 @@ jwt-decode@^3.1.2: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== -keycloakify@^8.1.3: - version "8.1.3" - resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.1.3.tgz#813836b013dc93d5cf43a5b476c9f19537e5435c" - integrity sha512-KdAvtqslWNggqtLAgWmPkWxiOK/tfkbxTJUmQw5DGXig1NNpdm39WRRtg9MjLnAlwsRfWw/uOdvlBR95x/5g3g== +keycloakify@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.2.1.tgz#5f817f1c14499f59564e96b06f33401bbe42a948" + integrity sha512-qSOSZx7Nc0LFf/8dzCdnlUvE40n2cvDRFqSNEs1rJ/iXKu7HsB+Wd7SEpUYJdBJxe8UexqofaNM2Fii7denyWw== dependencies: "@babel/generator" "^7.22.9" "@babel/parser" "^7.22.7" From 619faa53d521db491e03b91e63acfff4f2aa0b0a Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 22 Oct 2023 16:22:50 +0200 Subject: [PATCH 12/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef71e7e..a04241d 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.8.0", + "version": "4.8.1", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From 203a438c7c91bc6cbc14d60f862de89941f067b9 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Tue, 24 Oct 2023 13:42:23 +0200 Subject: [PATCH 13/23] Update oidc-spa --- package.json | 2 +- src/App/App.tsx | 80 +++++++++++++++++++++---------------------------- yarn.lock | 8 ++--- 3 files changed, 39 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index a04241d..420da5f 100755 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "keywords": [], "dependencies": { "evt": "^2.4.15", - "oidc-spa": "^1.0.1", + "oidc-spa": "^2.0.2", "keycloakify": "^8.2.1", "powerhooks": "^0.26.8", "react": "18.1.0", diff --git a/src/App/App.tsx b/src/App/App.tsx index 8fd8a10..6a3975f 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -3,7 +3,6 @@ import logo from "./logo.svg"; import myimg from "./myimg.png"; import { useMemo } from "react"; import { createOidcProvider, useOidc } from "oidc-spa/react"; -import { addQueryParamToUrl } from "oidc-spa/tools/urlQueryParams"; import { decodeJwt } from "oidc-spa"; import { assert } from "tsafe/assert"; @@ -16,31 +15,29 @@ const keycloakClientId= "starter"; const { OidcProvider } = createOidcProvider({ issuerUri: `${keycloakUrl}/realms/${keycloakRealm}`, clientId: keycloakClientId, - transformUrlBeforeRedirect: url => { - + // NOTE: You can also pass queries params when calling oidc.login() + getExtraQueryParams: () => ({ // This adding ui_locales to the url will ensure the consistency of the language between the app and the login pages // If your app implements a i18n system (like i18nifty.dev for example) you should use this and replace "en" by the // current language of the app. // On the other side you will find kcContext.locale.currentLanguageTag to be whatever you set here. - url = addQueryParamToUrl({ - url, - "name": "ui_locales", - "value": "en", - }).newUrl; - - // If you want to pass some custom state to the login pages... - // See in src/keycloak-theme/pages/Login.tsx how it's retrieved. - url = addQueryParamToUrl({ - url, - "name": "my_custom_param", - "value": "value of foo transferred to login page", - }).newUrl; - - return url; - - }, - // Uncomment if your app is not hosted at the origin and update /foo/bar/baz. - //silentSsoUrl: `${window.location.origin}/foo/bar/baz/silent-sso.html`, + "ui_locales": "en", + "my_custom_param": "value of foo transferred to login page" + }), + /* + * This parameter have to be provided provide if your App is not hosted at the origin of the subdomain. + * For example if your site is hosted by navigating to `https://www.example.com` + * you don't have to provide this parameter. + * On the other end if your site is hosted by navigating to `https://www.example.com/my-app` + * Then you want to set publicUrl to `/my-app` + * + * Be mindful that `${window.location.origin}${publicUrl}/silent-sso.html` must return the `silent-sso.html` that + * you are supposed to have created in your `public/` directory. + * + * If your are still using `create-react-app` (like we are for now) you can just set + * publicUrl to `process.env.PUBLIC_URL` and don't have to think about it further. + */ + publicUrl: process.env.PUBLIC_URL }); export default function App() { @@ -63,7 +60,13 @@ function ContextualizedApp() { oidc.isUserLoggedIn ? oidc.logout({ redirectTo: "home" })} /> : - + } logo test_image @@ -126,32 +129,17 @@ function buildAccountUrl( locale: string; } ){ - const { locale } = params; - let accountUrl = `${keycloakUrl}/realms/${keycloakRealm}/account`; + const accountUrl = new URL(`${keycloakUrl}/realms/${keycloakRealm}/account`); - // Set the language the user will get on the account page - accountUrl = addQueryParamToUrl({ - url: accountUrl, - name: "kc_locale", - value: locale - }).newUrl; + const searchParams = new URLSearchParams(); - // Enable to redirect to the app from the account page we'll get the referrer_uri under kcContext.referrer.url - // It's useful to avoid hard coding the app url in the keycloak config - accountUrl = addQueryParamToUrl({ - url: accountUrl, - name: "referrer", - value: keycloakClientId - }).newUrl; + searchParams.append("kc_locale", locale); + searchParams.append("referrer", keycloakClientId); + searchParams.append("referrer_uri", window.location.href); - accountUrl = addQueryParamToUrl({ - url: accountUrl, - name: "referrer_uri", - value: window.location.href - }).newUrl; + accountUrl.search = searchParams.toString(); - return accountUrl; - -} + return accountUrl.toString(); +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0747665..7851615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10917,10 +10917,10 @@ oidc-client-ts@^2.3.0: crypto-js "^4.1.1" jwt-decode "^3.1.2" -oidc-spa@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-1.0.1.tgz#205a7613def6b7aea9b4c2ad71e952180f8c3dcb" - integrity sha512-vrd0peFSSHphVNEvS1s76ZR21fQr1tPBuwQLK6MyReMN9r9HA+BfDOFEiYs1Q9nixrecMQVDQsF7nBxQfwSscA== +oidc-spa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/oidc-spa/-/oidc-spa-2.0.2.tgz#7a6c64f0e92c0f9349742974648627a85865a8b8" + integrity sha512-PILedvHPxy5U1Kwkpukdw5DW3adST/Bo6vZz70o7hwe59kwBVmVATBlAikZlscZn4x5pAeOyWuD1fir0N1WrJg== dependencies: jwt-decode "^3.1.2" oidc-client-ts "^2.3.0" From 716d3d4bda25a581e38a17688bcb5f072927adb2 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Tue, 24 Oct 2023 13:42:40 +0200 Subject: [PATCH 14/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 420da5f..a2f257e 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.8.1", + "version": "4.8.2", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From 0ac8461b86bfc52857013ff4e3ac886af71ce7e6 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 2 Nov 2023 20:06:17 +0100 Subject: [PATCH 15/23] Start storybook using the ./public dir as static asset dir --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a2f257e..7247574 100755 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "start": "react-scripts start", "build": "react-scripts build", "build-keycloak-theme": "yarn build && keycloakify", - "storybook": "start-storybook -p 6006" + "storybook": "start-storybook -p 6006 --static-dir ./public" }, "keycloakify": { "extraThemeProperties": [ @@ -84,4 +84,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} From 23a71f8fa077a73c1880c55adb0fb9c69f94de57 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 2 Nov 2023 21:04:16 +0100 Subject: [PATCH 16/23] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7247574..693863f 100755 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "start": "react-scripts start", "build": "react-scripts build", "build-keycloak-theme": "yarn build && keycloakify", - "storybook": "start-storybook -p 6006 --static-dir ./public" + "storybook": "start-storybook -p 6006" }, "keycloakify": { "extraThemeProperties": [ From bb019e66fb09166cb9af1e24e230994f59daa420 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 2 Nov 2023 21:27:34 +0100 Subject: [PATCH 17/23] Show how to import custom fonts in Storybook --- src/keycloak-theme/login/Template.tsx | 8 ++++++-- src/keycloak-theme/login/createPageStory.tsx | 8 +++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/keycloak-theme/login/Template.tsx b/src/keycloak-theme/login/Template.tsx index 871bca1..cb663b9 100644 --- a/src/keycloak-theme/login/Template.tsx +++ b/src/keycloak-theme/login/Template.tsx @@ -50,8 +50,12 @@ export default function Template(props: TemplateProps) { return (
-
- {msg("loginTitleHtml", realm.displayNameHtml)} +
+ {msg("loginTitleHtml", realm.displayNameHtml)}!!!
diff --git a/src/keycloak-theme/login/createPageStory.tsx b/src/keycloak-theme/login/createPageStory.tsx index cdf570f..24a5d70 100644 --- a/src/keycloak-theme/login/createPageStory.tsx +++ b/src/keycloak-theme/login/createPageStory.tsx @@ -15,7 +15,13 @@ export function createPageStory(params: { storyPartialKcContext: params.kcContext }); - return ; + return ( + <> + {/* If you import custom fonts in your index.html you have to import them in storybook as well*/} + + + + ); } From 211240b156a20dc3b74fdebafcb3c6cde9f22954 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 2 Nov 2023 21:33:30 +0100 Subject: [PATCH 18/23] Update index.html --- public/index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 0bcab1a..abf6ae5 100644 --- a/public/index.html +++ b/public/index.html @@ -21,6 +21,7 @@ + + + + + + diff --git a/yarn.lock b/yarn.lock index 7851615..acd153d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9760,10 +9760,10 @@ jwt-decode@^3.1.2: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== -keycloakify@^8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.2.1.tgz#5f817f1c14499f59564e96b06f33401bbe42a948" - integrity sha512-qSOSZx7Nc0LFf/8dzCdnlUvE40n2cvDRFqSNEs1rJ/iXKu7HsB+Wd7SEpUYJdBJxe8UexqofaNM2Fii7denyWw== +keycloakify@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/keycloakify/-/keycloakify-8.4.0.tgz#62f25c4f3e7701de9daf894192e2d38879cd2893" + integrity sha512-mZ6HXRZkkhFdQvK/mMMTDwrJ3cBzS85skcs/r3xvYT+P06EoLVfG8KBQuyy9IOdke+0ZHjylDV4E4UvWVCqPGw== dependencies: "@babel/generator" "^7.22.9" "@babel/parser" "^7.22.7" From ffecc6d4fdc1e3007c2b7ee40f9166f2f141e222 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sun, 19 Nov 2023 03:39:02 +0100 Subject: [PATCH 20/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c88a538..4e7e67f 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.8.2", + "version": "4.9.0", "description": "A starter/demo project for keycloakify", "repository": { "type": "git", From 2b99e94457b5d36b63ae8454ebffc566e4cd55a3 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Wed, 22 Nov 2023 11:44:12 +0100 Subject: [PATCH 21/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b8cf65..b694b3d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Keycloak theme that goes along with it. If you are only looking to create a theme (and not a theme + an App) there are a lot of things that you can remove from this starter: [Please read this section of the README](#standalone-keycloak-theme). > ❗️ WARNING ❗️: Don't waste time trying to port this setup to [Vite](https://vitejs.dev/). -> Currently Keycloakify only works collocated with Webpack projects but [we are working toward enabling collocation with Vite and Next.js projects](https://github.com/keycloakify/keycloakify/pull/275)! +> Currently Keycloakify only works collocated with Webpack projects but [we are working toward enabling collocation with Vite](https://github.com/keycloakify/keycloakify/pull/275)! # Quick start From aa4101740ef04b3d1ba4c66bf22eae6f4b4a4fb8 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 23 Nov 2023 03:52:40 +0100 Subject: [PATCH 22/23] Update link to storybook --- src/App/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App/App.tsx b/src/App/App.tsx index 6a3975f..ed71f44 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -71,7 +71,7 @@ function ContextualizedApp() { logo test_image

Hello world

-

Check out all keycloak pages in the Storybook!

+

Check out all keycloak pages in the Storybook!

Once you've identified the ones you want to customize run npx eject-keycloak-page

From f84990fac904c4bb32e199b14a470d9e69d3c71d Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Thu, 23 Nov 2023 03:52:55 +0100 Subject: [PATCH 23/23] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e7e67f..c3b8ce7 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "keycloakify-starter", "homepage": "https://starter.keycloakify.dev", - "version": "4.9.0", + "version": "4.9.1", "description": "A starter/demo project for keycloakify", "repository": { "type": "git",