diff --git a/federation/kerberos/pom.xml b/federation/kerberos/pom.xml
index 95e483b06bf..cf21b968d88 100755
--- a/federation/kerberos/pom.xml
+++ b/federation/kerberos/pom.xml
@@ -55,6 +55,16 @@
jboss-logging
provided
+
+ junit
+ junit
+ test
+
+
+ org.hamcrest
+ hamcrest
+ test
+
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
index d9c3d2074a6..b5e36f0806b 100644
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
@@ -22,8 +22,6 @@ import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.representations.idm.ComponentRepresentation;
-import java.util.Map;
-
/**
* Common configuration useful for all providers
*
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
index a197a5355fb..54bd05328b5 100755
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
@@ -38,6 +38,7 @@ import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderFactory;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.utils.CredentialHelper;
+import org.keycloak.component.ComponentValidationException;
import java.util.List;
@@ -168,4 +169,23 @@ public class KerberosFederationProviderFactory implements UserStorageProviderFac
CredentialHelper.setOrReplaceAuthenticationRequirement(session, realm, CredentialRepresentation.KERBEROS,
AuthenticationExecutionModel.Requirement.DISABLED, null);
}
+
+ @Override
+ public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel config) throws ComponentValidationException {
+ // Trim whitespace from string configuration values
+ trimConfigValue(config, KerberosConstants.SERVER_PRINCIPAL);
+ trimConfigValue(config, KerberosConstants.KERBEROS_REALM);
+ trimConfigValue(config, KerberosConstants.KEYTAB);
+ }
+
+ private void trimConfigValue(ComponentModel config, String configKey) {
+ String value = config.getConfig().getFirst(configKey);
+ if (value != null) {
+ String trimmedValue = value.trim();
+ if (!value.equals(trimmedValue)) {
+ // Update the config with trimmed value
+ config.getConfig().putSingle(configKey, trimmedValue);
+ }
+ }
+ }
}
diff --git a/federation/kerberos/src/test/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactoryTest.java b/federation/kerberos/src/test/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactoryTest.java
new file mode 100644
index 00000000000..cfc28c6eab8
--- /dev/null
+++ b/federation/kerberos/src/test/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactoryTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2024 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.federation.kerberos;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+
+/**
+ * Tests for KerberosFederationProviderFactory validation functionality.
+ */
+public class KerberosFederationProviderFactoryTest {
+
+ @Test
+ public void testValidateConfigurationTrimsValues() throws Exception {
+ KerberosFederationProviderFactory factory = new KerberosFederationProviderFactory();
+
+ ComponentModel config = new ComponentModel();
+ MultivaluedHashMap configMap = new MultivaluedHashMap<>();
+ configMap.add(KerberosConstants.SERVER_PRINCIPAL, " myPrincipal ");
+ configMap.add(KerberosConstants.KERBEROS_REALM, " MYREALM.COM ");
+ configMap.add(KerberosConstants.KEYTAB, " /path/to/keytab ");
+ config.setConfig(configMap);
+
+ // Mock session and realm (not used in current implementation)
+ KeycloakSession session = null;
+ RealmModel realm = null;
+
+ // Call validateConfiguration
+ factory.validateConfiguration(session, realm, config);
+
+ // Verify values are trimmed
+ Assert.assertEquals("myPrincipal", config.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
+ Assert.assertEquals("MYREALM.COM", config.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
+ Assert.assertEquals("/path/to/keytab", config.getConfig().getFirst(KerberosConstants.KEYTAB));
+ }
+
+ @Test
+ public void testValidateConfigurationHandlesNullValues() throws Exception {
+ KerberosFederationProviderFactory factory = new KerberosFederationProviderFactory();
+
+ ComponentModel config = new ComponentModel();
+ MultivaluedHashMap configMap = new MultivaluedHashMap<>();
+ config.setConfig(configMap);
+
+ // Mock session and realm (not used in current implementation)
+ KeycloakSession session = null;
+ RealmModel realm = null;
+
+ // Call validateConfiguration - should not throw exception
+ factory.validateConfiguration(session, realm, config);
+
+ // Verify null values remain null
+ Assert.assertNull(config.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
+ Assert.assertNull(config.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
+ Assert.assertNull(config.getConfig().getFirst(KerberosConstants.KEYTAB));
+ }
+
+ @Test
+ public void testValidateConfigurationHandlesAlreadyTrimmedValues() throws Exception {
+ KerberosFederationProviderFactory factory = new KerberosFederationProviderFactory();
+
+ ComponentModel config = new ComponentModel();
+ MultivaluedHashMap configMap = new MultivaluedHashMap<>();
+ configMap.add(KerberosConstants.SERVER_PRINCIPAL, "myPrincipal");
+ configMap.add(KerberosConstants.KERBEROS_REALM, "MYREALM.COM");
+ configMap.add(KerberosConstants.KEYTAB, "/path/to/keytab");
+ config.setConfig(configMap);
+
+ // Mock session and realm (not used in current implementation)
+ KeycloakSession session = null;
+ RealmModel realm = null;
+
+ // Call validateConfiguration
+ factory.validateConfiguration(session, realm, config);
+
+ // Verify values remain unchanged
+ Assert.assertEquals("myPrincipal", config.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL));
+ Assert.assertEquals("MYREALM.COM", config.getConfig().getFirst(KerberosConstants.KERBEROS_REALM));
+ Assert.assertEquals("/path/to/keytab", config.getConfig().getFirst(KerberosConstants.KEYTAB));
+ }
+}
\ No newline at end of file