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 4ddd142f23..d95abdb7d1 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 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 43a9634527..b3f652075c 100755 --- 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; @@ -302,6 +303,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 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);