Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ The `Use Truststore SPI` configuration property is deprecated. It should normal

If you set the *Import Users* option, the LDAP Provider handles importing LDAP users into the {project_name} local database. The first time a user logs in or is returned as part of a user query (e.g. using the search field in the admin console), the LDAP provider imports the LDAP user into the {project_name} database. During authentication, the LDAP password is validated.

By default, {project_name} does not support the username and email attributes with case-sensitive values when storing users to the local database. The value for these attributes will be stored in lower-case in the local database.
However, if the *Import Users* option is disabled, {project_name} will not lower-case the username and email attributes when querying users from LDAP.
This behavior allows you to use case-sensitive usernames and emails when *Import Users* is disabled. Note that this behavior applies only to username and email attributes. Other attributes remain case-sensitive.

It is recommended to not use case-sensitive usernames and emails when using LDAP with {project_name}, as some features in {project_name} may not work correctly with case-sensitive usernames and emails.

If you want to sync all LDAP users into the {project_name} database, configure and enable the *Sync Settings* on the LDAP provider configuration page.

Two types of synchronization exist:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.keycloak.storage.ldap;

import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;

import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.models.LDAPConstants;
import org.keycloak.storage.UserStorageProvider;
Expand Down Expand Up @@ -284,6 +286,10 @@ public boolean isEdirectory() {
return LDAPConstants.VENDOR_NOVELL_EDIRECTORY.equalsIgnoreCase(getVendor());
}

public boolean isImportEnabled() {
return Boolean.parseBoolean(config.getFirstOrDefault(IMPORT_ENABLED, Boolean.TRUE.toString())) ;
}

@Override
public int hashCode() {
return config.hashCode() * 13 + binaryAttributeNames.hashCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ public static String getUsername(LDAPObject ldapUser, LDAPConfig config) {
config.getUsernameLdapAttribute() + ", user DN: " + ldapUser.getDn() + ", attributes from LDAP: " + ldapUser.getAttributes());
}

return Optional.of(ldapUsername).map(String::toLowerCase).orElse(null);
if (config.isImportEnabled()) {
return Optional.of(ldapUsername).map(String::toLowerCase).orElse(null);
}

return ldapUsername;
}

public static void checkUuid(LDAPObject ldapUser, LDAPConfig config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ public void setEmailVerified(boolean verified) {
public String getUsername() {
if (UserModel.USERNAME.equals(userModelAttrName)) {
return ofNullable(ldapUser.getAttributeAsString(ldapAttrName))
.map(String::toLowerCase)
.map(this::toLowerCaseIfImportEnabled)
.orElse(null);
}
return super.getUsername();
Expand All @@ -307,7 +307,7 @@ public String getUsername() {
public String getEmail() {
if (UserModel.EMAIL.equals(userModelAttrName)) {
return ofNullable(ldapUser.getAttributeAsString(ldapAttrName))
.map(String::toLowerCase)
.map(this::toLowerCaseIfImportEnabled)
.orElse(null);
}
return super.getEmail();
Expand Down Expand Up @@ -349,6 +349,12 @@ protected boolean setLDAPAttribute(String modelAttrName, Object value) {
return true;
}

private String toLowerCaseIfImportEnabled(String value) {
if (getLdapProvider().getModel().isImportEnabled()) {
return value.toLowerCase();
}
return value;
}
};

} else if (isBinaryAttribute) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ searchClientByName=Search client by name
loginTimeout=Login timeout
attributeName=Attribute [Name]
updateError=Could not update the provider {{error}}
importUsersHelp=If true, LDAP users will be imported into the Keycloak database and synced by the configured sync policies.
importUsersHelp=If true, LDAP users will be imported into the local database and synced by the configured sync policies. If import is enabled, the username and email attributes will be stored in the local database using case-insensitivity values, in lower-case. If disabled, those attributes will be treated as case-sensitive and the values will have the same format from their corresponding LDAP entries.
emptyClientProfilesInstructions=There are no profiles, select 'Create client profile' to create a new client profile
policyProvider.js=Define conditions for your permissions using JavaScript. It is one of the rule-based policy types supported by Keycloak, and provides flexibility to write any policy based on the Evaluation API.
idpType.social=Social login
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,7 @@ public UserStorageProviderModel(ComponentModel copy) {

public boolean isImportEnabled() {
if (importEnabled == null) {
String val = getConfig().getFirst(IMPORT_ENABLED);
if (val == null) {
importEnabled = true;
} else {
importEnabled = Boolean.valueOf(val);
}
importEnabled = Boolean.parseBoolean(getConfig().getFirstOrDefault(IMPORT_ENABLED, Boolean.TRUE.toString()));
}
return importEnabled;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,30 @@ public void caseInsensitiveSearch() {
}

@Test
public void testUsernameAndEmailInLowerCaseFromLDAP() {
public void testUsernameAndEmailCaseSensitiveIfImportDisabled() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
UserStorageProviderModel ldapModel = ctx.getLdapProvider().getModel();
ldapModel.setImportEnabled(false);
ctx.getRealm().updateComponent(ldapModel);
LDAPObject ldapObject = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "JBrown8", "John", "Brown8", "[email protected]", null, "1234");
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), ldapObject, "Password1");
UserModel model = session.users().searchForUserStream(ctx.getRealm(), Map.of(UserModel.USERNAME, "JBrown8")).findAny().orElse(null);
Assert.assertNotNull(model);
assertEquals("JBrown8", model.getUsername());
assertEquals("[email protected]", model.getEmail());
ldapModel.setImportEnabled(true);
ctx.getRealm().updateComponent(ldapModel);
});
}

@Test
public void testUsernameAndEmailCaseInSensitiveIfImportEnabled() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
UserStorageProviderModel ldapModel = ctx.getLdapProvider().getModel();
ldapModel.setImportEnabled(true);
ctx.getRealm().updateComponent(ldapModel);
LDAPObject ldapObject = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "JBrown9", "John", "Brown9", "[email protected]", null, "1234");
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), ldapObject, "Password1");
UserModel model = session.users().searchForUserStream(ctx.getRealm(), Map.of(UserModel.USERNAME, "JBrown9")).findAny().orElse(null);
Expand Down
Loading