diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
index 4ddd142..d95abdb 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
@@ -229,7 +229,9 @@ public class LDAPFederationProvider implements UserFederationProvider {
List<UserModel> result = new ArrayList<>();
for (String username : usernames) {
UserModel kcUser = session.users().getUserByUsername(username, realm);
- if (!model.getId().equals(kcUser.getFederationLink())) {
+ if (kcUser == null) {
+ logger.warnf("User '%s' referenced by membership wasn't found in LDAP", username);
+ } else if (!model.getId().equals(kcUser.getFederationLink())) {
logger.warnf("Incorrect federation provider of user %s" + kcUser.getUsername());
} else {
result.add(kcUser);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperTest.java
index 45afc47..89abefc 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperTest.java
@@ -31,6 +31,7 @@ import org.junit.runners.MethodSorters;
import org.keycloak.federation.ldap.LDAPFederationProvider;
import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
import org.keycloak.federation.ldap.LDAPUtils;
+import org.keycloak.federation.ldap.idm.model.LDAPDn;
import org.keycloak.federation.ldap.idm.model.LDAPObject;
import org.keycloak.federation.ldap.mappers.membership.LDAPGroupMapperMode;
import org.keycloak.federation.ldap.mappers.membership.MembershipType;
@@ -300,6 +301,47 @@ public class LDAPGroupMapperTest {
}
}
+
+ // KEYCLOAK-2682
+ @Test
+ public void test04_groupReferencingNonExistentMember() {
+ KeycloakSession session = keycloakRule.startSession();
+ try {
+ RealmModel appRealm = session.realms().getRealmByName("test");
+
+ UserFederationMapperModel mapperModel = appRealm.getUserFederationMapperByName(ldapModel.getId(), "groupsMapper");
+ FederationTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.MODE, LDAPGroupMapperMode.LDAP_ONLY.toString());
+ appRealm.updateUserFederationMapper(mapperModel);
+
+ // 1 - Add some group to LDAP for testing
+ LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
+ GroupLDAPFederationMapper groupMapper = FederationTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm);
+ LDAPObject group2 = FederationTestUtils.createLDAPGroup(session, appRealm, ldapModel, "group2", descriptionAttrName, "group2 - description");
+
+ // 2 - Add one existing user rob to LDAP group
+ LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak");
+ LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group2, robLdap, false);
+
+ // 3 - Add non-existing user to LDAP group
+ LDAPDn nonExistentDn = LDAPDn.fromString(ldapProvider.getLdapIdentityStore().getConfig().getUsersDn());
+ nonExistentDn.addFirst(robLdap.getRdnAttributeName(), "nonexistent");
+ LDAPObject nonExistentLdapUser = new LDAPObject();
+ nonExistentLdapUser.setDn(nonExistentDn);
+ LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, group2, nonExistentLdapUser, true);
+
+ // 4 - Check group members. Just existing user rob should be present
+ groupMapper.syncDataFromFederationProviderToKeycloak();
+ GroupModel kcGroup2 = KeycloakModelUtils.findGroupByPath(appRealm, "/group2");
+ List<UserModel> groupUsers = session.users().getGroupMembers(appRealm, kcGroup2, 0, 5);
+ Assert.assertEquals(1, groupUsers.size());
+ UserModel rob = groupUsers.get(0);
+ Assert.assertEquals("robkeycloak", rob.getUsername());
+
+ } finally {
+ keycloakRule.stopSession(session, false);
+ }
+ }
+
private void deleteGroupMappingsInLDAP(GroupLDAPFederationMapper groupMapper, LDAPObject ldapUser, String groupName) {
LDAPObject ldapGroup = groupMapper.loadLDAPGroupByName(groupName);
groupMapper.deleteGroupMappingInLDAP(ldapUser, ldapGroup);