Lowercase username and email when fetching values from LDAP object

Closes #43254

Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
Pedro Igor 2025-10-07 11:14:50 -03:00 committed by GitHub
parent ab7939f33a
commit 54289f0130
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 3 deletions

View File

@ -27,6 +27,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -185,7 +186,7 @@ public class LDAPUtils {
config.getUsernameLdapAttribute() + ", user DN: " + ldapUser.getDn() + ", attributes from LDAP: " + ldapUser.getAttributes()); config.getUsernameLdapAttribute() + ", user DN: " + ldapUser.getDn() + ", attributes from LDAP: " + ldapUser.getAttributes());
} }
return ldapUsername; return Optional.of(ldapUsername).map(String::toLowerCase).orElse(null);
} }
public static void checkUuid(LDAPObject ldapUser, LDAPConfig config) { public static void checkUuid(LDAPObject ldapUser, LDAPConfig config) {

View File

@ -17,6 +17,8 @@
package org.keycloak.storage.ldap.mappers; package org.keycloak.storage.ldap.mappers;
import static java.util.Optional.ofNullable;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.component.ComponentModel; import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -46,6 +48,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -293,7 +296,9 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
@Override @Override
public String getUsername() { public String getUsername() {
if (UserModel.USERNAME.equals(userModelAttrName)) { if (UserModel.USERNAME.equals(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName); return ofNullable(ldapUser.getAttributeAsString(ldapAttrName))
.map(String::toLowerCase)
.orElse(null);
} }
return super.getUsername(); return super.getUsername();
} }
@ -301,7 +306,9 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
@Override @Override
public String getEmail() { public String getEmail() {
if (UserModel.EMAIL.equals(userModelAttrName)) { if (UserModel.EMAIL.equals(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName); return ofNullable(ldapUser.getAttributeAsString(ldapAttrName))
.map(String::toLowerCase)
.orElse(null);
} }
return super.getEmail(); return super.getEmail();
} }

View File

@ -457,6 +457,19 @@ public class LDAPProvidersIntegrationTest extends AbstractLDAPTest {
Assert.assertEquals("jbrown5@email.org", user5.getEmail()); Assert.assertEquals("jbrown5@email.org", user5.getEmail());
} }
@Test
public void testUsernameAndEmailInLowerCaseFromLDAP() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
LDAPObject ldapObject = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "JBrown9", "John", "Brown9", "JBrown9@Email.org", null, "1234");
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), ldapObject, "Password1");
UserModel model = session.users().searchForUserStream(ctx.getRealm(), Map.of(UserModel.USERNAME, "JBrown9")).findAny().orElse(null);
Assert.assertNotNull(model);
assertEquals("jbrown9", model.getUsername());
assertEquals("jbrown9@email.org", model.getEmail());
});
}
@Test @Test
public void deleteFederationLink() throws Exception { public void deleteFederationLink() throws Exception {
// KEYCLOAK-4789: Login in client, which requires consent // KEYCLOAK-4789: Login in client, which requires consent