From f2f3cd148fc210bea7b167b7a16b2d328a71399f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 May 2026 20:45:51 +0000
Subject: [PATCH 1/3] Initial plan
From 6c4d787a37095bec05f720b819b7b1f0585039a6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 May 2026 20:49:51 +0000
Subject: [PATCH 2/3] fix: hide locale in deferred registration
Agent-Logs-Url: https://github.com/sequentech/step/sessions/db61abf7-a447-4d11-9473-d575c09724c7
Co-authored-by: edulix <81968+edulix@users.noreply.github.com>
---
.../login/user-profile-commons.ftl | 3 +
.../voter-enrollment/pom.xml | 6 ++
.../DeferredRegistrationUserCreation.java | 7 ++
.../DeferredRegistrationUserCreationTest.java | 67 +++++++++++++++++++
4 files changed, 83 insertions(+)
create mode 100644 packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
diff --git a/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl b/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
index 027f7012d48..9c9b032a188 100644
--- a/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
+++ b/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
@@ -12,6 +12,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<#assign disabledElements = []>
<#list profile.attributes as attribute>
+ <#if attribute.name == "locale">
+ <#continue>
+ #if>
<#-- Check for default custom attribute and assign it the first time the form is opened -->
<#if attribute.values?has_content>
<#assign values = attribute.values>
diff --git a/packages/keycloak-extensions/voter-enrollment/pom.xml b/packages/keycloak-extensions/voter-enrollment/pom.xml
index ac203732bd3..2e3a617a6c8 100644
--- a/packages/keycloak-extensions/voter-enrollment/pom.xml
+++ b/packages/keycloak-extensions/voter-enrollment/pom.xml
@@ -25,6 +25,12 @@ SPDX-License-Identifier: AGPL-3.0-only
message-otp-authenticator
${project.version}
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.11.4
+ test
+
diff --git a/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java b/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
index 759c04ba51d..6b6956b4f1d 100644
--- a/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
+++ b/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
@@ -220,6 +220,7 @@ public void validate(ValidationContext context) {
&& !Messages.USERNAME_EXISTS.equals(error.getMessage()))
&& !Messages.EMAIL_EXISTS.equals(error.getMessage())
// If username is hidden ignore the missing username validation error.
+ && !isLocaleRequiredError(error)
&& !(Messages.MISSING_USERNAME.equals(error.getMessage())
&& "true"
.equals(
@@ -614,10 +615,16 @@ private MultivaluedMap normalizeFormParameters(
// user-profile data
copy.remove(RegistrationPage.FIELD_PASSWORD);
copy.remove(RegistrationPage.FIELD_PASSWORD_CONFIRM);
+ copy.remove(UserModel.LOCALE);
return copy;
}
+ static boolean isLocaleRequiredError(ValidationException.Error error) {
+ return UserModel.LOCALE.equals(error.getAttribute())
+ && MISSING_FIELDS_ERROR.equals(error.getMessage());
+ }
+
/**
* Get user profile instance for current HTTP request (KeycloakSession) and for given context.
* This assumes that there is single user registered within HTTP request, which is always the case
diff --git a/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java b/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
new file mode 100644
index 00000000000..9413e4f66aa
--- /dev/null
+++ b/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
@@ -0,0 +1,67 @@
+// SPDX-FileCopyrightText: 2026 Sequent Tech
+//
+// SPDX-License-Identifier: AGPL-3.0-only
+package sequent.keycloak.voter_enrollment;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.lang.reflect.Method;
+import org.junit.jupiter.api.Test;
+import org.keycloak.authentication.forms.RegistrationPage;
+import org.keycloak.models.UserModel;
+import org.keycloak.userprofile.ValidationException;
+import org.keycloak.validate.ValidationError;
+
+class DeferredRegistrationUserCreationTest {
+
+ @Test
+ void normalizeFormParametersRemovesLocaleAndSensitiveFields() throws Exception {
+ MultivaluedMap formParams = new MultivaluedHashMap<>();
+ formParams.add(RegistrationPage.FIELD_PASSWORD, "password");
+ formParams.add(RegistrationPage.FIELD_PASSWORD_CONFIRM, "password");
+ formParams.add(UserModel.LOCALE, "en");
+ formParams.add(UserModel.EMAIL, "voter@example.com");
+
+ Method method =
+ DeferredRegistrationUserCreation.class.getDeclaredMethod(
+ "normalizeFormParameters", MultivaluedMap.class);
+ method.setAccessible(true);
+
+ @SuppressWarnings("unchecked")
+ MultivaluedMap normalized =
+ (MultivaluedMap)
+ method.invoke(new DeferredRegistrationUserCreation(), formParams);
+
+ assertFalse(normalized.containsKey(RegistrationPage.FIELD_PASSWORD));
+ assertFalse(normalized.containsKey(RegistrationPage.FIELD_PASSWORD_CONFIRM));
+ assertFalse(normalized.containsKey(UserModel.LOCALE));
+ assertTrue(normalized.containsKey(UserModel.EMAIL));
+ }
+
+ @Test
+ void isLocaleRequiredErrorOnlyMatchesRequiredLocale() {
+ ValidationException.Error localeRequiredError =
+ new ValidationException.Error(
+ new ValidationError(
+ "required",
+ UserModel.LOCALE,
+ DeferredRegistrationUserCreation.MISSING_FIELDS_ERROR));
+ ValidationException.Error localeInvalidError =
+ new ValidationException.Error(
+ new ValidationError(
+ "validator", UserModel.LOCALE, ValidationError.MESSAGE_INVALID_VALUE));
+ ValidationException.Error emailRequiredError =
+ new ValidationException.Error(
+ new ValidationError(
+ "required",
+ UserModel.EMAIL,
+ DeferredRegistrationUserCreation.MISSING_FIELDS_ERROR));
+
+ assertTrue(DeferredRegistrationUserCreation.isLocaleRequiredError(localeRequiredError));
+ assertFalse(DeferredRegistrationUserCreation.isLocaleRequiredError(localeInvalidError));
+ assertFalse(DeferredRegistrationUserCreation.isLocaleRequiredError(emailRequiredError));
+ }
+}
From 28d4b36c7ac9e71ceba4efb53fc3a6916c798aad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 May 2026 21:06:44 +0000
Subject: [PATCH 3/3] fix: configure hidden locale in registration action
Agent-Logs-Url: https://github.com/sequentech/step/sessions/dfc939c6-7138-4f01-88f5-84ee0d7c85af
Co-authored-by: edulix <81968+edulix@users.noreply.github.com>
---
.../sequent.admin-portal/login/user-profile-commons.ftl | 2 +-
packages/keycloak-extensions/voter-enrollment/pom.xml | 2 +-
.../voter_enrollment/DeferredRegistrationUserCreation.java | 3 +++
.../DeferredRegistrationUserCreationTest.java | 6 ++++++
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl b/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
index 9c9b032a188..1e32dec0c42 100644
--- a/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
+++ b/packages/keycloak-extensions/sequent-theme/src/main/resources/theme/sequent.admin-portal/login/user-profile-commons.ftl
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<#assign disabledElements = []>
<#list profile.attributes as attribute>
- <#if attribute.name == "locale">
+ <#if hiddenProfileAttributes?? && hiddenProfileAttributes?seq_contains(attribute.name)>
<#continue>
#if>
<#-- Check for default custom attribute and assign it the first time the form is opened -->
diff --git a/packages/keycloak-extensions/voter-enrollment/pom.xml b/packages/keycloak-extensions/voter-enrollment/pom.xml
index 2e3a617a6c8..ae6fe6d1fbf 100644
--- a/packages/keycloak-extensions/voter-enrollment/pom.xml
+++ b/packages/keycloak-extensions/voter-enrollment/pom.xml
@@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
org.junit.jupiter
junit-jupiter
- 5.11.4
+ 6.0.3
test
diff --git a/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java b/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
index 6b6956b4f1d..8fe95371ba7 100644
--- a/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
+++ b/packages/keycloak-extensions/voter-enrollment/src/main/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreation.java
@@ -15,6 +15,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.jbosslog.JBossLog;
@@ -94,6 +95,7 @@ public String getValue() {
public static final String INVALID_INPUT = "Invalid input";
public static final String MISSING_FIELDS_ERROR = "error_user_attribute_required";
+ public static final Set HIDDEN_PROFILE_ATTRIBUTES = Set.of(UserModel.LOCALE);
@Override
public String getHelpText() {
@@ -502,6 +504,7 @@ public void buildPage(FormContext context, LoginFormsProvider form) {
form.setAttribute("passwordRequired", passwordRequired);
form.setAttribute("formMode", formMode);
+ form.setAttribute("hiddenProfileAttributes", HIDDEN_PROFILE_ATTRIBUTES);
log.infov("buildPage(): formMode = {0}", formMode);
checkNotOtherUserAuthenticating(context);
}
diff --git a/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java b/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
index 9413e4f66aa..970db973142 100644
--- a/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
+++ b/packages/keycloak-extensions/voter-enrollment/src/test/java/sequent/keycloak/voter_enrollment/DeferredRegistrationUserCreationTest.java
@@ -41,6 +41,12 @@ void normalizeFormParametersRemovesLocaleAndSensitiveFields() throws Exception {
assertTrue(normalized.containsKey(UserModel.EMAIL));
}
+ @Test
+ void hiddenProfileAttributesIncludesLocale() {
+ assertTrue(
+ DeferredRegistrationUserCreation.HIDDEN_PROFILE_ATTRIBUTES.contains(UserModel.LOCALE));
+ }
+
@Test
void isLocaleRequiredErrorOnlyMatchesRequiredLocale() {
ValidationException.Error localeRequiredError =