From e3a0639a0ca07a8cec21835a35b8899c4d44c35b Mon Sep 17 00:00:00 2001 From: Mary Strodl Date: Tue, 4 Oct 2022 00:35:04 -0400 Subject: [PATCH] Add `login-username` support Shown for the "Username Form" login step. I would also like to work on: - `login-password.ftl` - `webauthn-authenticate.ftl` But first want to see opinions on this! --- package.json | 1 + .../keycloakify/generateFtl/generateFtl.ts | 1 + src/lib/components/KcApp.tsx | 3 + src/lib/components/LoginUsername.tsx | 168 +++++++++++ src/lib/getKcContext/KcContextBase.ts | 31 ++ .../kcContextMocks/kcContextMocks.ts | 21 ++ yarn.lock | 270 +++++++++++++++++- 7 files changed, 491 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/LoginUsername.tsx diff --git a/package.json b/package.json index d6a3f7c2..75b92642 100755 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "devDependencies": { + "@babel/core": "^7.0.0", "@emotion/react": "^11.4.1", "@types/memoizee": "^0.4.7", "@types/minimist": "^1.2.2", diff --git a/src/bin/keycloakify/generateFtl/generateFtl.ts b/src/bin/keycloakify/generateFtl/generateFtl.ts index 3674f5d8..e1bfb3b9 100644 --- a/src/bin/keycloakify/generateFtl/generateFtl.ts +++ b/src/bin/keycloakify/generateFtl/generateFtl.ts @@ -13,6 +13,7 @@ import { Reflect } from "tsafe/Reflect"; // https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/forms/login/freemarker/Templates.java export const pageIds = [ "login.ftl", + "login-username.ftl", "register.ftl", "register-user-profile.ftl", "info.ftl", diff --git a/src/lib/components/KcApp.tsx b/src/lib/components/KcApp.tsx index 51f7a662..f18f64cb 100644 --- a/src/lib/components/KcApp.tsx +++ b/src/lib/components/KcApp.tsx @@ -13,6 +13,7 @@ const LoginResetPassword = lazy(() => import("./LoginResetPassword")); const LoginVerifyEmail = lazy(() => import("./LoginVerifyEmail")); const Terms = lazy(() => import("./Terms")); const LoginOtp = lazy(() => import("./LoginOtp")); +const LoginUsername = lazy(() => import("./LoginUsername")); const LoginUpdatePassword = lazy(() => import("./LoginUpdatePassword")); const LoginUpdateProfile = lazy(() => import("./LoginUpdateProfile")); const LoginIdpLinkConfirm = lazy(() => import("./LoginIdpLinkConfirm")); @@ -67,6 +68,8 @@ const KcApp = memo( return ; case "login-otp.ftl": return ; + case "login-username.ftl": + return ; case "login-update-password.ftl": return ; case "login-update-profile.ftl": diff --git a/src/lib/components/LoginUsername.tsx b/src/lib/components/LoginUsername.tsx new file mode 100644 index 00000000..4c8415a0 --- /dev/null +++ b/src/lib/components/LoginUsername.tsx @@ -0,0 +1,168 @@ +import React, { useState, memo } from "react"; +import Template from "./Template"; +import type { KcProps } from "./KcProps"; +import type { KcContextBase } from "../getKcContext/KcContextBase"; +import { useCssAndCx } from "../tools/useCssAndCx"; +import { useConstCallback } from "powerhooks/useConstCallback"; +import type { FormEventHandler } from "react"; +import type { I18n } from "../i18n"; + +const LoginUsername = memo( + ({ + kcContext, + i18n, + doFetchDefaultThemeResources = true, + ...props + }: { kcContext: KcContextBase.LoginUsername; i18n: I18n; doFetchDefaultThemeResources?: boolean } & KcProps) => { + const { social, realm, url, usernameHidden, login, registrationDisabled } = kcContext; + + const { msg, msgStr } = i18n; + + const { cx } = useCssAndCx(); + + const [isLoginButtonDisabled, setIsLoginButtonDisabled] = useState(false); + + const onSubmit = useConstCallback>(e => { + e.preventDefault(); + + setIsLoginButtonDisabled(true); + + const formElement = e.target as HTMLFormElement; + + //NOTE: Even if we login with email Keycloak expect username and password in + //the POST request. + formElement.querySelector("input[name='email']")?.setAttribute("name", "username"); + + formElement.submit(); + }); + + return ( +