KEYCLOAK-13817 Fix X509 auth fails
when attribute value is always read from LDAP and import is enabled When userattribute value is always read from LDAP, then the value is not available in the local store. Therfore, KC will not find a user by that attribute in the local store. When querying the LDAP storage provider, the user will be found. However, when it is also available in the local store (though without the attribute) it will not get imported and therefore not returned with the result set of the LDAP storage provider. Hence, the user will not be found at all. This change adds the user to the result set of the LDAP user stoage provider, iff the attribute user by the search is set to always read value from LDAP.
This commit is contained in:
parent
f7d00fc2e9
commit
fed34929ae
2 changed files with 23 additions and 7 deletions
|
@ -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<ComponentModel> 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;
|
||||
}
|
||||
|
|
|
@ -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<Object> userModelProperty, UserModel user, String ldapAttrValue) {
|
||||
if (ldapAttrValue == null) {
|
||||
|
|
Loading…
Reference in a new issue