Delete broker links for federated users when an identity provider is deleted

Closes #13731
This commit is contained in:
Arnaud Martin 2022-08-16 16:22:39 +02:00 committed by Marek Posolda
parent ddcf0f45f9
commit af0d97e534
2 changed files with 78 additions and 2 deletions

View file

@ -212,11 +212,12 @@ public class JpaUserFederatedStorageProvider implements
return true;
}
@Override
@Override
public void preRemove(RealmModel realm, IdentityProviderModel provider) {
em.createNamedQuery("deleteBrokerLinkByIdentityProvider")
.setParameter("realmId", realm.getId())
.setParameter("providerAlias", provider.getAlias());
.setParameter("providerAlias", provider.getAlias())
.executeUpdate();
}
private BrokerLinkEntity getBrokerLinkEntity(RealmModel realm, String userId, String socialProvider) {

View file

@ -16,10 +16,14 @@
*/
package org.keycloak.testsuite.broker;
import java.util.Collections;
import javax.ws.rs.core.Response;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.common.Profile;
import org.keycloak.common.Profile.Feature;
@ -31,12 +35,16 @@ import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.ProfileAssume;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
import org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProvider;
import org.keycloak.testsuite.federation.PassThroughFederatedUserStorageProviderFactory;
import org.keycloak.testsuite.federation.UserMapStorageFactory;
import org.keycloak.testsuite.pages.AccountFederatedIdentityPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.UpdateAccountInformationPage;
@ -47,9 +55,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
import org.keycloak.testsuite.runonserver.RunOnServer;
import org.keycloak.testsuite.util.FederatedIdentityBuilder;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -170,6 +183,68 @@ public class AccountLinkTest extends AbstractKeycloakTest {
getTestingClient().server(CHILD_IDP).run(AccountLinkTest::checkEmptyFederatedIdentities);
}
@Test
public void testDeleteFederatedUserFederatedIdentityOnProviderRemoval() {
RealmResource realm = adminClient.realm(CHILD_IDP);
final String testIdpToDelete = "test-idp-to-delete";
BrokerTestTools.createKcOidcBroker(adminClient, CHILD_IDP, testIdpToDelete);
// Create user federation
Assume.assumeTrue("User cache disabled.", isUserCacheEnabled());
ComponentRepresentation memProvider = new ComponentRepresentation();
memProvider.setName("memory");
memProvider.setProviderId(UserMapStorageFactory.PROVIDER_ID);
memProvider.setProviderType(UserStorageProvider.class.getName());
memProvider.setConfig(new MultivaluedHashMap<>());
memProvider.getConfig().putSingle("priority", Integer.toString(0));
memProvider.getConfig().putSingle(IMPORT_ENABLED, Boolean.toString(false));
Response resp = realm.components().add(memProvider);
resp.close();
String memProviderId = ApiUtil.getCreatedId(resp);
// Create federated user
String username = "fedUser1";
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setUsername(username);
userRepresentation.setEmail("feduser1@mail.com");
userRepresentation.setRequiredActions(Collections.emptyList());
userRepresentation.setEnabled(true);
userRepresentation.setFederationLink(memProviderId);
String userId = createUserWithAdminClient(realm, userRepresentation);
Assert.assertFalse(StorageId.isLocalStorage(userId));
// Link identity provider and federated user
FederatedIdentityRepresentation identity = FederatedIdentityBuilder.create()
.userId(userId)
.userName(username)
.identityProvider(testIdpToDelete)
.build();
UserResource userResource = realm.users().get(userId);
Response response = userResource.addFederatedIdentity(testIdpToDelete, identity);
Assert.assertEquals("status", 204, response.getStatus());
userResource = realm.users().get(userId);
Assert.assertFalse(userResource.getFederatedIdentity().isEmpty());
// Delete the identity provider
realm.identityProviders().get(testIdpToDelete).remove();
// Check that links to federated identity has been deleted
userResource = realm.users().get(userId);
Assert.assertTrue(userResource.getFederatedIdentity().isEmpty());
getTestingClient().server(CHILD_IDP).run((RunOnServer) session -> {
RealmModel realm1 = session.getContext().getRealm();
UserModel user = session.users().getUserByUsername(realm1, username);
assertEquals(0, session.users().getFederatedIdentitiesStream(realm1, user).count());
assertNull(session.users().getFederatedIdentity(realm1, user, testIdpToDelete));
});
}
private static void checkEmptyFederatedIdentities(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();