diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java index 70499a55e6..15ecb919f4 100755 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java @@ -35,7 +35,6 @@ import org.keycloak.credential.CredentialAuthentication; import org.keycloak.credential.CredentialInput; import org.keycloak.credential.CredentialInputUpdater; import org.keycloak.credential.CredentialInputValidator; -import org.keycloak.credential.CredentialModel; import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; import org.keycloak.models.*; @@ -58,10 +57,7 @@ import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery; import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.storage.ldap.kerberos.LDAPProviderKerberosConfig; -import org.keycloak.storage.ldap.mappers.LDAPOperationDecorator; -import org.keycloak.storage.ldap.mappers.LDAPStorageMapper; -import org.keycloak.storage.ldap.mappers.LDAPStorageMapperManager; -import org.keycloak.storage.ldap.mappers.PasswordUpdateCallback; +import org.keycloak.storage.ldap.mappers.*; import org.keycloak.storage.user.ImportedUserValidation; import org.keycloak.storage.user.UserLookupProvider; import org.keycloak.storage.user.UserQueryProvider; @@ -237,9 +233,12 @@ public class LDAPStorageProvider implements UserStorageProvider, for (LDAPObject ldapUser : ldapObjects) { String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig()); - if (session.userLocalStorage().getUserByUsername(ldapUsername, realm) == null) { + UserModel localUser = session.userLocalStorage().getUserByUsername(ldapUsername, realm); + if (localUser == null) { UserModel imported = importUserFromLDAP(session, realm, ldapUser); searchResults.add(imported); + } else if (shouldUserAttributeBeAlwaysReadFromLdap(realm, attrName)) { + searchResults.add(proxy(realm, localUser, ldapUser)); } } @@ -247,6 +246,20 @@ public class LDAPStorageProvider implements UserStorageProvider, } } + private boolean shouldUserAttributeBeAlwaysReadFromLdap(RealmModel realm, String userAttributeName) { + List mapperModels = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName()); + return mapperModels.stream().anyMatch(mapperModel -> shouldUserAttributeBeAlwaysReadFromLdap(mapperModel, userAttributeName)); + } + + private boolean shouldUserAttributeBeAlwaysReadFromLdap(ComponentModel mapperModel, String userAttributeName) { + LDAPStorageMapper mapper = mapperManager.getMapper(mapperModel); + if (UserAttributeLDAPStorageMapper.class.isAssignableFrom(mapper.getClass())) { + UserAttributeLDAPStorageMapper userAttributeMapper = (UserAttributeLDAPStorageMapper) mapper; + return userAttributeName.equals(userAttributeMapper.getUserModelAttribute()) && userAttributeMapper.isAlwaysReadValueFromLdap(); + } + return false; + } + public boolean synchronizeRegistrations() { return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == UserStorageProvider.EditMode.WRITABLE; } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java index 6f3f454c83..eb83f53cd4 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java @@ -415,7 +415,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper { } } - private String getUserModelAttribute() { + public String getUserModelAttribute() { return mapperModel.getConfig().getFirst(USER_MODEL_ATTRIBUTE); } @@ -431,6 +431,9 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper { return parseBooleanParameter(mapperModel, READ_ONLY); } + public boolean isAlwaysReadValueFromLdap() { + return parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP); + } protected void setPropertyOnUserModel(Property userModelProperty, UserModel user, String ldapAttrValue) { if (ldapAttrValue == null) {