keycloak-aplcache

Details

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);