keycloak-aplcache

hynek db changes

1/30/2018 8:00:55 PM

Changes

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index e2fcc83..be3d0ad 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -54,6 +54,7 @@ import org.keycloak.storage.CacheableStorageProviderModel;
 import org.keycloak.storage.StorageId;
 import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.storage.client.ClientStorageProvider;
 
 import java.util.Calendar;
 import java.util.HashMap;
@@ -853,7 +854,7 @@ public class UserCacheSession implements UserCache {
 
     @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
-        if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return;
+        if (!component.getProviderType().equals(UserStorageProvider.class.getName()) && !component.getProviderType().equals(ClientStorageProvider.class.getName())) return;
         addRealmInvalidation(realm.getId()); // easier to just invalidate whole realm
         getDelegate().preRemove(realm, component);
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
index a29ab69..9772810 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
@@ -43,11 +43,14 @@ import java.util.Collection;
 })
 @NamedQueries({
         @NamedQuery(name="userConsentByUserAndClient", query="select consent from UserConsentEntity consent where consent.user.id = :userId and consent.clientId = :clientId"),
+        @NamedQuery(name="userConsentByUserAndExternalClient", query="select consent from UserConsentEntity consent where consent.user.id = :userId and consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"),
         @NamedQuery(name="userConsentsByUser", query="select consent from UserConsentEntity consent where consent.user.id = :userId"),
         @NamedQuery(name="deleteUserConsentsByRealm", query="delete from UserConsentEntity consent where consent.user IN (select user from UserEntity user where user.realmId = :realmId)"),
         @NamedQuery(name="deleteUserConsentsByRealmAndLink", query="delete from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link)"),
         @NamedQuery(name="deleteUserConsentsByUser", query="delete from UserConsentEntity consent where consent.user = :user"),
         @NamedQuery(name="deleteUserConsentsByClient", query="delete from UserConsentEntity consent where consent.clientId = :clientId"),
+        @NamedQuery(name="deleteUserConsentsByExternalClient", query="delete from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"),
+        @NamedQuery(name="deleteUserConsentsByClientStorageProvider", query="delete from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider"),
 })
 public class UserConsentEntity {
 
@@ -63,6 +66,12 @@ public class UserConsentEntity {
     @Column(name="CLIENT_ID")
     protected String clientId;
 
+    @Column(name="CLIENT_STORAGE_PROVIDER")
+    protected String clientStorageProvider;
+
+    @Column(name="EXTERNAL_CLIENT_ID")
+    protected String externalClientId;
+
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
     Collection<UserConsentRoleEntity> grantedRoles = new ArrayList<UserConsentRoleEntity>();
 
@@ -91,14 +100,6 @@ public class UserConsentEntity {
         this.user = user;
     }
 
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(String clientId) {
-        this.clientId = clientId;
-    }
-
     public Collection<UserConsentRoleEntity> getGrantedRoles() {
         return grantedRoles;
     }
@@ -131,6 +132,30 @@ public class UserConsentEntity {
         this.lastUpdatedDate = lastUpdatedDate;
     }
 
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getClientStorageProvider() {
+        return clientStorageProvider;
+    }
+
+    public void setClientStorageProvider(String clientStorageProvider) {
+        this.clientStorageProvider = clientStorageProvider;
+    }
+
+    public String getExternalClientId() {
+        return externalClientId;
+    }
+
+    public void setExternalClientId(String externalClientId) {
+        this.externalClientId = externalClientId;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java
index 4c0dd5d..85df759 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentProtocolMapperEntity.java
@@ -38,7 +38,9 @@ import java.io.Serializable;
         @NamedQuery(name="deleteUserConsentProtMappersByUser", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"),
         @NamedQuery(name="deleteUserConsentProtMappersByRealmAndLink", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.user IN (select u from UserEntity u where u.realmId=:realmId and u.federationLink=:link))"),
         @NamedQuery(name="deleteUserConsentProtMappersByProtocolMapper", query="delete from UserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId)"),
-        @NamedQuery(name="deleteUserConsentProtMappersByClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId))"),
+        @NamedQuery(name="deleteUserConsentProtMappersByClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"),
+        @NamedQuery(name="deleteUserConsentProtMappersByExternalClient", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
+        @NamedQuery(name="deleteUserConsentProtMappersByClientStorageProvider", query="delete from UserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
 })
 @Entity
 @Table(name="USER_CONSENT_PROT_MAPPER")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java
index 95d5f3e..c4818c7 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentRoleEntity.java
@@ -38,6 +38,8 @@ import java.io.Serializable;
         @NamedQuery(name="deleteUserConsentRolesByUser", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.user = :user)"),
         @NamedQuery(name="deleteUserConsentRolesByRole", query="delete from UserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId)"),
         @NamedQuery(name="deleteUserConsentRolesByClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientId = :clientId)"),
+        @NamedQuery(name="deleteUserConsentRolesByExternalClient", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
+        @NamedQuery(name="deleteUserConsentRolesByClientStorageProvider", query="delete from UserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from UserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
 })
 @Entity
 @Table(name="USER_CONSENT_ROLE")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index 08f3164..8eb8102 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -45,7 +45,9 @@ import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
 import org.keycloak.models.jpa.entities.UserEntity;
 import org.keycloak.models.utils.DefaultRoles;
 import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.storage.StorageId;
 import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.client.ClientStorageProvider;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
@@ -194,7 +196,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
         consentEntity = new UserConsentEntity();
         consentEntity.setId(KeycloakModelUtils.generateId());
         consentEntity.setUser(em.getReference(UserEntity.class, userId));
-        consentEntity.setClientId(clientId);
+        StorageId clientStorageId = new StorageId(clientId);
+        if (clientStorageId.isLocal()) {
+            consentEntity.setClientId(clientId);
+        } else {
+            consentEntity.setClientStorageProvider(clientStorageId.getProviderId());
+            consentEntity.setExternalClientId(clientStorageId.getExternalId());
+        }
+
         consentEntity.setCreatedDate(currentTime);
         consentEntity.setLastUpdatedDate(currentTime);
         em.persist(consentEntity);
@@ -246,9 +255,16 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
 
 
     private UserConsentEntity getGrantedConsentEntity(String userId, String clientId) {
-        TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
+        StorageId clientStorageId = new StorageId(clientId);
+        String queryName = clientStorageId.isLocal() ?  "userConsentByUserAndClient" : "userConsentByUserAndExternalClient";
+        TypedQuery<UserConsentEntity> query = em.createNamedQuery(queryName, UserConsentEntity.class);
         query.setParameter("userId", userId);
-        query.setParameter("clientId", clientId);
+        if (clientStorageId.isLocal()) {
+            query.setParameter("clientId", clientId);
+        } else {
+            query.setParameter("clientStorageProvider", clientStorageId.getProviderId());
+            query.setParameter("externalClientId", clientStorageId.getExternalId());
+        }
         List<UserConsentEntity> results = query.getResultList();
         if (results.size() > 1) {
             throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]");
@@ -257,6 +273,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
         } else {
             return null;
         }
+
     }
 
     private UserConsentModel toConsentModel(RealmModel realm, UserConsentEntity entity) {
@@ -264,9 +281,16 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
             return null;
         }
 
-        ClientModel client = realm.getClientById(entity.getClientId());
+        StorageId clientStorageId = null;
+        if ( entity.getClientId() == null) {
+            clientStorageId = new StorageId(entity.getClientStorageProvider(), entity.getExternalClientId());
+        } else {
+            clientStorageId = new StorageId(entity.getClientId());
+        }
+
+        ClientModel client = realm.getClientById(clientStorageId.getId());
         if (client == null) {
-            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+            throw new ModelException("Client with id " + clientStorageId.getId() + " is not available");
         }
         UserConsentModel model = new UserConsentModel(client);
         model.setCreatedDate(entity.getCreatedDate());
@@ -472,9 +496,32 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
 
     @Override
     public void preRemove(RealmModel realm, ClientModel client) {
-        em.createNamedQuery("deleteUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
+        StorageId clientStorageId = new StorageId(client.getId());
+        if (clientStorageId.isLocal()) {
+            em.createNamedQuery("deleteUserConsentProtMappersByClient")
+                    .setParameter("clientId", client.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteUserConsentRolesByClient")
+                    .setParameter("clientId", client.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteUserConsentsByClient")
+                    .setParameter("clientId", client.getId())
+                    .executeUpdate();
+        } else {
+            em.createNamedQuery("deleteUserConsentProtMappersByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId",clientStorageId.getExternalId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteUserConsentRolesByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId", clientStorageId.getExternalId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteUserConsentsByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId", clientStorageId.getExternalId())
+                    .executeUpdate();
+
+        }
     }
 
     @Override
@@ -806,8 +853,24 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
 
     @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
-        if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return;
-        removeImportedUsers(realm, component.getId());
+        if (component.getProviderType().equals(UserStorageProvider.class.getName())) {
+            removeImportedUsers(realm, component.getId());
+        }
+        if (component.getProviderType().equals(ClientStorageProvider.class.getName())) {
+            removeConsentByClientStorageProvider(realm, component.getId());
+        }
+    }
+
+    protected void removeConsentByClientStorageProvider(RealmModel realm, String providerId) {
+        em.createNamedQuery("deleteUserConsentProtMappersByClientStorageProvider")
+                .setParameter("clientStorageProvider", providerId)
+                .executeUpdate();
+        em.createNamedQuery("deleteUserConsentRolesByClientStorageProvider")
+                .setParameter("clientStorageProvider", providerId)
+                .executeUpdate();
+        em.createNamedQuery("deleteUserConsentsByClientStorageProvider")
+                .setParameter("clientStorageProvider", providerId)
+                .executeUpdate();
 
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java
index 225e80b..c2eac0b 100755
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentEntity.java
@@ -40,11 +40,14 @@ import java.util.Collection;
 })
 @NamedQueries({
         @NamedQuery(name="userFederatedConsentByUserAndClient", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.clientId = :clientId"),
+        @NamedQuery(name="userFederatedConsentByUserAndExternalClient", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId and consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"),
         @NamedQuery(name="userFederatedConsentsByUser", query="select consent from FederatedUserConsentEntity consent where consent.userId = :userId"),
         @NamedQuery(name="deleteFederatedUserConsentsByRealm", query="delete from FederatedUserConsentEntity consent where consent.realmId=:realmId"),
         @NamedQuery(name="deleteFederatedUserConsentsByStorageProvider", query="delete from FederatedUserConsentEntity e where e.storageProviderId=:storageProviderId"),
         @NamedQuery(name="deleteFederatedUserConsentsByUser", query="delete from FederatedUserConsentEntity consent where consent.userId = :userId and consent.realmId = :realmId"),
         @NamedQuery(name="deleteFederatedUserConsentsByClient", query="delete from FederatedUserConsentEntity consent where consent.clientId = :clientId"),
+        @NamedQuery(name="deleteFederatedUserConsentsByExternalClient", query="delete from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId"),
+        @NamedQuery(name="deleteFederatedUserConsentsByClientStorageProvider", query="delete from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider"),
 })
 public class FederatedUserConsentEntity {
 
@@ -65,6 +68,12 @@ public class FederatedUserConsentEntity {
     @Column(name="CLIENT_ID")
     protected String clientId;
 
+    @Column(name="CLIENT_STORAGE_PROVIDER")
+    protected String clientStorageProvider;
+
+    @Column(name="EXTERNAL_CLIENT_ID")
+    protected String externalClientId;
+
     @Column(name = "CREATED_DATE")
     private Long createdDate;
 
@@ -119,6 +128,22 @@ public class FederatedUserConsentEntity {
         this.clientId = clientId;
     }
 
+    public String getClientStorageProvider() {
+        return clientStorageProvider;
+    }
+
+    public void setClientStorageProvider(String clientStorageProvider) {
+        this.clientStorageProvider = clientStorageProvider;
+    }
+
+    public String getExternalClientId() {
+        return externalClientId;
+    }
+
+    public void setExternalClientId(String externalClientId) {
+        this.externalClientId = externalClientId;
+    }
+
     public Collection<FederatedUserConsentRoleEntity> getGrantedRoles() {
         return grantedRoles;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java
index f7da2cc..a9de2c6 100755
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentProtocolMapperEntity.java
@@ -39,6 +39,8 @@ import java.io.Serializable;
         @NamedQuery(name="deleteFederatedUserConsentProtMappersByStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
         @NamedQuery(name="deleteFederatedUserConsentProtMappersByProtocolMapper", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.protocolMapperId = :protocolMapperId"),
         @NamedQuery(name="deleteFederatedUserConsentProtMappersByClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
+        @NamedQuery(name="deleteFederatedUserConsentProtMappersByExternalClient", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
+        @NamedQuery(name="deleteFederatedUserConsentProtMappersByClientStorageProvider", query="delete from FederatedUserConsentProtocolMapperEntity csm where csm.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
 })
 @Entity
 @Table(name="FED_USER_CONSENT_PROT_MAPPER")
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java
index d74865d..0e0551d 100755
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUserConsentRoleEntity.java
@@ -38,6 +38,8 @@ import java.io.Serializable;
         @NamedQuery(name="deleteFederatedUserConsentRolesByStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.storageProviderId = :storageProviderId)"),
         @NamedQuery(name="deleteFederatedUserConsentRolesByRole", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.roleId = :roleId"),
         @NamedQuery(name="deleteFederatedUserConsentRolesByClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientId = :clientId)"),
+        @NamedQuery(name="deleteFederatedUserConsentRolesByExternalClient", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider and consent.externalClientId = :externalClientId)"),
+        @NamedQuery(name="deleteFederatedUserConsentRolesByClientStorageProvider", query="delete from FederatedUserConsentRoleEntity grantedRole where grantedRole.userConsent IN (select consent from FederatedUserConsentEntity consent where consent.clientStorageProvider = :clientStorageProvider)"),
 })
 @Entity
 @Table(name="FED_USER_CONSENT_ROLE")
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
index f6de431..7474155 100644
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
@@ -32,9 +32,11 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserConsentModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.jpa.entities.UserConsentEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.storage.StorageId;
 import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.client.ClientStorageProvider;
 import org.keycloak.storage.federated.UserFederatedStorageProvider;
 import org.keycloak.storage.jpa.entity.BrokerLinkEntity;
 import org.keycloak.storage.jpa.entity.FederatedUser;
@@ -257,7 +259,13 @@ public class JpaUserFederatedStorageProvider implements
         consentEntity = new FederatedUserConsentEntity();
         consentEntity.setId(KeycloakModelUtils.generateId());
         consentEntity.setUserId(userId);
-        consentEntity.setClientId(clientId);
+        StorageId clientStorageId = new StorageId(clientId);
+        if (clientStorageId.isLocal()) {
+            consentEntity.setClientId(clientId);
+        } else {
+            consentEntity.setClientStorageProvider(clientStorageId.getProviderId());
+            consentEntity.setExternalClientId(clientStorageId.getExternalId());
+        }
         consentEntity.setRealmId(realm.getId());
         consentEntity.setStorageProviderId(new StorageId(userId).getProviderId());
         long currentTime = Time.currentTimeMillis();
@@ -315,9 +323,16 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     private FederatedUserConsentEntity getGrantedConsentEntity(String userId, String clientId) {
-        TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentByUserAndClient", FederatedUserConsentEntity.class);
+        StorageId clientStorageId = new StorageId(clientId);
+        String queryName = clientStorageId.isLocal() ?  "userFederatedConsentByUserAndClient" : "userFederatedConsentByUserAndExternalClient";
+        TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery(queryName, FederatedUserConsentEntity.class);
         query.setParameter("userId", userId);
-        query.setParameter("clientId", clientId);
+        if (clientStorageId.isLocal()) {
+            query.setParameter("clientId", clientId);
+        } else {
+            query.setParameter("clientStorageProvider", clientStorageId.getProviderId());
+            query.setParameter("externalClientId", clientStorageId.getExternalId());
+        }
         List<FederatedUserConsentEntity> results = query.getResultList();
         if (results.size() > 1) {
             throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]");
@@ -334,10 +349,14 @@ public class JpaUserFederatedStorageProvider implements
             return null;
         }
 
-        ClientModel client = realm.getClientById(entity.getClientId());
-        if (client == null) {
-            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+        StorageId clientStorageId = null;
+        if ( entity.getClientId() == null) {
+            clientStorageId = new StorageId(entity.getClientStorageProvider(), entity.getExternalClientId());
+        } else {
+            clientStorageId = new StorageId(entity.getClientId());
         }
+
+        ClientModel client = realm.getClientById(clientStorageId.getId());
         UserConsentModel model = new UserConsentModel(client);
         model.setCreatedDate(entity.getCreatedDate());
         model.setLastUpdatedDate(entity.getLastUpdatedDate());
@@ -822,9 +841,26 @@ public class JpaUserFederatedStorageProvider implements
 
     @Override
     public void preRemove(RealmModel realm, ClientModel client) {
-        em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
-        em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
+        StorageId clientStorageId = new StorageId(client.getId());
+        if (clientStorageId.isLocal()) {
+            em.createNamedQuery("deleteFederatedUserConsentProtMappersByClient").setParameter("clientId", client.getId()).executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentRolesByClient").setParameter("clientId", client.getId()).executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentsByClient").setParameter("clientId", client.getId()).executeUpdate();
+        } else {
+            em.createNamedQuery("deleteFederatedUserConsentProtMappersByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId",clientStorageId.getExternalId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentRolesByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId",clientStorageId.getExternalId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentsByExternalClient")
+                    .setParameter("clientStorageProvider", clientStorageId.getProviderId())
+                    .setParameter("externalClientId",clientStorageId.getExternalId())
+                    .executeUpdate();
+
+        }
     }
 
     @Override
@@ -885,41 +921,53 @@ public class JpaUserFederatedStorageProvider implements
 
     @Override
     public void preRemove(RealmModel realm, ComponentModel model) {
-        if (!model.getProviderType().equals(UserStorageProvider.class.getName())) return;
+        if (model.getProviderType().equals(UserStorageProvider.class.getName())) {
+
+            em.createNamedQuery("deleteBrokerLinkByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedAttributesByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedCredentialAttributeByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserCredentialsByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserGroupMembershipByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserRequiredActionsByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUsersByStorageProvider")
+                    .setParameter("storageProviderId", model.getId())
+                    .executeUpdate();
+        } else if (model.getProviderType().equals(ClientStorageProvider.class.getName())) {
+            em.createNamedQuery("deleteFederatedUserConsentProtMappersByClientStorageProvider")
+                    .setParameter("clientStorageProvider", model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentRolesByClientStorageProvider")
+                    .setParameter("clientStorageProvider",  model.getId())
+                    .executeUpdate();
+            em.createNamedQuery("deleteFederatedUserConsentsByClientStorageProvider")
+                    .setParameter("clientStorageProvider",  model.getId())
+                    .executeUpdate();
 
-        em.createNamedQuery("deleteBrokerLinkByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedAttributesByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserConsentProtMappersByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserConsentsByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedCredentialAttributeByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserCredentialsByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserGroupMembershipByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserRequiredActionsByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUserRoleMappingsByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
-        em.createNamedQuery("deleteFederatedUsersByStorageProvider")
-                .setParameter("storageProviderId", model.getId())
-                .executeUpdate();
+        }
 
     }
 }
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml
index 859f2a7..09a1d80 100644
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-4.0.0.xml
@@ -41,8 +41,32 @@
 
         <!--  Modify USER_CONSENT -->
         <dropUniqueConstraint constraintName="UK_JKUWUVD56ONTGSUHOGM8UEWRT" tableName="USER_CONSENT"/>
-        <modifyDataType tableName="USER_CONSENT" columnName="CLIENT_ID" newDataType="VARCHAR(255)"/>
-        <addUniqueConstraint columnNames="CLIENT_ID, USER_ID" constraintName="UK_JKUWUVD56ONTGSUHOGM8UEWRT" tableName="USER_CONSENT"/>
+        <dropNotNullConstraint tableName="USER_CONSENT" columnName="CLIENT_ID" columnDataType="VARCHAR(36)"/>
+        <addColumn tableName="USER_CONSENT">
+            <column name="CLIENT_STORAGE_PROVIDER" type="VARCHAR(36)">
+                <constraints nullable="true"/>
+            </column>
+            <column name="EXTERNAL_CLIENT_ID" type="VARCHAR(255)">
+                <constraints nullable="true"/>
+            </column>
+        </addColumn>
+        <addUniqueConstraint columnNames="CLIENT_ID, CLIENT_STORAGE_PROVIDER, EXTERNAL_CLIENT_ID, USER_ID" constraintName="UK_JKUWUVD56ONTGSUHOGM8UEWRT" tableName="USER_CONSENT"/>
+
+        <!-- FED_USER_CONSENT -->
+        <addColumn tableName="FED_USER_CONSENT">
+            <column name="CLIENT_STORAGE_PROVIDER" type="VARCHAR(36)">
+                <constraints nullable="true"/>
+            </column>
+            <column name="EXTERNAL_CLIENT_ID" type="VARCHAR(255)">
+                <constraints nullable="true"/>
+            </column>
+        </addColumn>
+        <dropNotNullConstraint tableName="FED_USER_CONSENT" columnName="CLIENT_ID" columnDataType="VARCHAR(36)"/>
+        <createIndex tableName="FED_USER_CONSENT" indexName="IDX_FU_CNSNT_EXT">
+            <column name="USER_ID" type="VARCHAR(255)" />
+            <column name="CLIENT_STORAGE_PROVIDER" type="VARCHAR(36)" />
+            <column name="EXTERNAL_CLIENT_ID" type="VARCHAR(255)" />
+        </createIndex>
 
         <!-- Modify CLIENT_NODE_REGISTRATIONS -->
         <dropForeignKeyConstraint constraintName="FK4129723BA992F594" baseTableName="CLIENT"/>
@@ -53,12 +77,5 @@
         <modifyDataType tableName="OFFLINE_CLIENT_SESSION" columnName="CLIENT_ID" newDataType="VARCHAR(255)"/>
         <addPrimaryKey columnNames="USER_SESSION_ID,CLIENT_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_CL_SES_PK3" tableName="OFFLINE_CLIENT_SESSION"/>
 
-        <!-- FED_USER_CONSENT -->
-        <dropIndex tableName="FED_USER_CONSENT" indexName="IDX_FU_CONSENT"/>
-        <modifyDataType tableName="FED_USER_CONSENT" columnName="CLIENT_ID" newDataType="VARCHAR(255)"/>
-        <createIndex tableName="FED_USER_CONSENT" indexName="IDX_FU_CONSENT">
-            <column name="USER_ID" type="VARCHAR(255)" />
-            <column name="CLIENT_ID" type="VARCHAR(36)" />
-        </createIndex>
-    </changeSet>
+     </changeSet>
 </databaseChangeLog>
diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
index 16d14e0..4801553 100755
--- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -40,6 +40,7 @@ import org.keycloak.models.cache.UserCache;
 import org.keycloak.models.utils.ComponentUtil;
 import org.keycloak.models.utils.ReadOnlyUserModelDelegate;
 import org.keycloak.services.managers.UserStorageSyncManager;
+import org.keycloak.storage.client.ClientStorageProvider;
 import org.keycloak.storage.federated.UserFederatedStorageProvider;
 import org.keycloak.storage.user.ImportedUserValidation;
 import org.keycloak.storage.user.UserBulkUpdateProvider;
@@ -696,6 +697,11 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo
 
     @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
+        if (component.getProviderType().equals(ClientStorageProvider.class.getName())) {
+            localStorage().preRemove(realm, component);
+            if (getFederatedStorage() != null) getFederatedStorage().preRemove(realm, component);
+            return;
+        }
         if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return;
         localStorage().preRemove(realm, component);
         if (getFederatedStorage() != null) getFederatedStorage().preRemove(realm, component);
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java
index e56c864..672cb1e 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java
@@ -42,12 +42,14 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
     protected ClientStorageProviderModel component;
     protected String clientId;
     protected String redirectUri;
+    protected boolean consent;
 
     public HardcodedClientStorageProvider(KeycloakSession session, ClientStorageProviderModel component) {
         this.session = session;
         this.component = component;
         this.clientId = component.getConfig().getFirst(HardcodedClientStorageProviderFactory.CLIENT_ID);
         this.redirectUri = component.getConfig().getFirst(HardcodedClientStorageProviderFactory.REDIRECT_URI);
+        this.consent = "true".equals(component.getConfig().getFirst(HardcodedClientStorageProviderFactory.CONSENT));
     }
 
     @Override
@@ -189,7 +191,7 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
 
         @Override
         public boolean isConsentRequired() {
-            return false;
+            return consent;
         }
 
         @Override
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java
index 6b2e480..67fcc0e 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProviderFactory.java
@@ -48,6 +48,7 @@ public class HardcodedClientStorageProviderFactory implements ClientStorageProvi
     public static final String CLIENT_ID = "client_id";
 
     public static final String REDIRECT_URI = "redirect_uri";
+    public static final String CONSENT = "consent";
 
     static {
         CONFIG_PROPERTIES = ProviderConfigurationBuilder.create()
@@ -58,11 +59,17 @@ public class HardcodedClientStorageProviderFactory implements ClientStorageProvi
                 .defaultValue("hardcoded-client")
                 .add()
                 .property().name(REDIRECT_URI)
-                .type(ProviderConfigProperty.BOOLEAN_TYPE)
+                .type(ProviderConfigProperty.STRING_TYPE)
                 .label("Redirect Uri")
                 .helpText("Valid redirect uri.  Only one allowed")
                 .defaultValue("http://localhost:8180/*")
                 .add()
+                .property().name(CONSENT)
+                .type(ProviderConfigProperty.BOOLEAN_TYPE)
+                .label("Consent Required")
+                .helpText("Is consent required")
+                .defaultValue("false")
+                .add()
                 .build();
     }
 
diff --git a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
index 9fe49f2..ced16a0 100644
--- a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
+++ b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
@@ -20,6 +20,7 @@ package org.keycloak.testsuite.model;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.keycloak.component.ComponentModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ModelException;
 import org.keycloak.models.ProtocolMapperModel;
@@ -30,6 +31,8 @@ import org.keycloak.models.UserConsentModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
+import org.keycloak.storage.client.ClientStorageProviderModel;
+import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
 
 import java.util.List;
 
@@ -38,6 +41,8 @@ import java.util.List;
  */
 public class UserConsentModelTest extends AbstractModelTest {
 
+    private ComponentModel clientStorageComponent;
+
     @Before
     public void setupEnv() {
         RealmModel realm = realmManager.createRealm("original");
@@ -87,6 +92,22 @@ public class UserConsentModelTest extends AbstractModelTest {
         maryFooGrant.addGrantedProtocolMapper(fooMapper);
         realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
 
+        ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
+        clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
+        clientStorage.setParentId(realm.getId());
+        clientStorageComponent = realm.addComponentModel(clientStorage);
+
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+
+        Assert.assertNotNull(hardcodedClient);
+
+        UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
+        realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
+
+
         commit();
     }
 
@@ -125,7 +146,15 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
         Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
 
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
+        Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0);
+        Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0);
+        Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
+        Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
+
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
     }
 
     @Test
@@ -139,14 +168,26 @@ public class UserConsentModelTest extends AbstractModelTest {
         List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john.getId());
         Assert.assertEquals(2, johnConsents.size());
 
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+
         List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
-        Assert.assertEquals(1, maryConsents.size());
+        Assert.assertEquals(2, maryConsents.size());
         UserConsentModel maryConsent = maryConsents.get(0);
+        UserConsentModel maryHardcodedConsent = maryConsents.get(1);
+        if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
+            maryConsent = maryConsents.get(1);
+            maryHardcodedConsent = maryConsents.get(0);
+
+        }
         Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
         Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
         Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
+
+        Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
+        Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0);
+        Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0);
     }
 
     @Test
@@ -190,14 +231,19 @@ public class UserConsentModelTest extends AbstractModelTest {
         RealmModel realm = realmManager.getRealm("original");
         ClientModel fooClient = realm.getClientByClientId("foo-client");
         UserModel john = session.users().getUserByUsername("john", realm);
+        UserModel mary = session.users().getUserByUsername("mary", realm);
 
         realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
 
         commit();
 
         realm = realmManager.getRealm("original");
         john = session.users().getUserByUsername("john", realm);
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId()));
+        mary = session.users().getUserByUsername("mary", realm);
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
     }
 
     @Test
@@ -206,6 +252,8 @@ public class UserConsentModelTest extends AbstractModelTest {
         RealmModel realm = realmManager.getRealm("original");
         UserModel john = session.users().getUserByUsername("john", realm);
         session.users().removeUser(realm, john);
+        UserModel mary = session.users().getUserByUsername("mary", realm);
+        session.users().removeUser(realm, mary);
     }
 
     @Test
@@ -270,6 +318,24 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId()));
     }
 
+    @Test
+    public void deleteClientStorageTest() {
+        RealmModel realm = realmManager.getRealm("original");
+        realm.removeComponent(clientStorageComponent);
+        commit();
+
+
+
+        realm = realmManager.getRealm("original");
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        Assert.assertNull(hardcodedClient);
+
+        UserModel mary = session.users().getUserByUsername("mary", realm);
+
+        List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
+        Assert.assertEquals(1, maryConsents.size());
+    }
+
     private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) {
         RoleModel role = roleContainer.getRole(roleName);
         return consentModel.isRoleGranted(role);
diff --git a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java
index 6fd18bf..04b5cde 100644
--- a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java
+++ b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/model/UserConsentWithUserStorageModelTest.java
@@ -20,6 +20,7 @@ package org.keycloak.testsuite.model;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.keycloak.component.ComponentModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ModelException;
 import org.keycloak.models.ProtocolMapperModel;
@@ -31,6 +32,8 @@ import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.mappers.UserPropertyMapper;
 import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.storage.client.ClientStorageProviderModel;
+import org.keycloak.testsuite.federation.HardcodedClientStorageProviderFactory;
 import org.keycloak.testsuite.federation.storage.UserMapStorageFactory;
 import org.keycloak.testsuite.federation.storage.UserPropertyFileStorageFactory;
 
@@ -41,6 +44,8 @@ import java.util.List;
  */
 public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
 
+    private ComponentModel clientStorageComponent;
+
     @Before
     public void setupEnv() {
         RealmModel realm = realmManager.createRealm("original");
@@ -97,6 +102,22 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         maryFooGrant.addGrantedProtocolMapper(fooMapper);
         realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
 
+        ClientStorageProviderModel clientStorage = new ClientStorageProviderModel();
+        clientStorage.setProviderId(HardcodedClientStorageProviderFactory.PROVIDER_ID);
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CLIENT_ID, "hardcoded-client");
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.REDIRECT_URI, "http://localhost:8081/*");
+        clientStorage.getConfig().putSingle(HardcodedClientStorageProviderFactory.CONSENT, "true");
+        clientStorage.setParentId(realm.getId());
+        clientStorageComponent = realm.addComponentModel(clientStorage);
+
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+
+        Assert.assertNotNull(hardcodedClient);
+
+        UserConsentModel maryHardcodedGrant = new UserConsentModel(hardcodedClient);
+        realmManager.getSession().users().addConsent(realm, mary.getId(), maryHardcodedGrant);
+
+
         commit();
     }
 
@@ -135,7 +156,15 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
         Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
 
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        UserConsentModel maryHardcodedConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId());
+        Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0);
+        Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0);
+        Assert.assertNotNull("Created Date should be set", maryHardcodedConsent.getCreatedDate());
+        Assert.assertNotNull("Last Updated Date should be set", maryHardcodedConsent.getLastUpdatedDate());
+
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), hardcodedClient.getId()));
     }
 
     @Test
@@ -149,14 +178,26 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john.getId());
         Assert.assertEquals(2, johnConsents.size());
 
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+
         List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
-        Assert.assertEquals(1, maryConsents.size());
+        Assert.assertEquals(2, maryConsents.size());
         UserConsentModel maryConsent = maryConsents.get(0);
+        UserConsentModel maryHardcodedConsent = maryConsents.get(1);
+        if (maryConsents.get(0).getClient().getId().equals(hardcodedClient.getId())) {
+            maryConsent = maryConsents.get(1);
+            maryHardcodedConsent = maryConsents.get(0);
+
+        }
         Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
         Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
         Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
+
+        Assert.assertEquals(maryHardcodedConsent.getClient().getId(), hardcodedClient.getId());
+        Assert.assertEquals(maryHardcodedConsent.getGrantedRoles().size(), 0);
+        Assert.assertEquals(maryHardcodedConsent.getGrantedProtocolMappers().size(), 0);
     }
 
     @Test
@@ -200,14 +241,19 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         RealmModel realm = realmManager.getRealm("original");
         ClientModel fooClient = realm.getClientByClientId("foo-client");
         UserModel john = session.users().getUserByUsername("john", realm);
+        UserModel mary = session.users().getUserByUsername("mary", realm);
 
         realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        realmManager.getSession().users().revokeConsentForClient(realm, mary.getId(), hardcodedClient.getId());
 
         commit();
 
         realm = realmManager.getRealm("original");
         john = session.users().getUserByUsername("john", realm);
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId()));
+        mary = session.users().getUserByUsername("mary", realm);
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), hardcodedClient.getId()));
     }
 
     @Test
@@ -216,6 +262,8 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         RealmModel realm = realmManager.getRealm("original");
         UserModel john = session.users().getUserByUsername("john", realm);
         session.users().removeUser(realm, john);
+        UserModel mary = session.users().getUserByUsername("mary", realm);
+        session.users().removeUser(realm, mary);
     }
 
     @Test
@@ -280,6 +328,24 @@ public class UserConsentWithUserStorageModelTest extends AbstractModelTest {
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId()));
     }
 
+    @Test
+    public void deleteClientStorageTest() {
+        RealmModel realm = realmManager.getRealm("original");
+        realm.removeComponent(clientStorageComponent);
+        commit();
+
+
+
+        realm = realmManager.getRealm("original");
+        ClientModel hardcodedClient = session.realms().getClientByClientId("hardcoded-client", realm);
+        Assert.assertNull(hardcodedClient);
+
+        UserModel mary = session.users().getUserByUsername("mary", realm);
+
+        List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
+        Assert.assertEquals(1, maryConsents.size());
+    }
+
     private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) {
         RoleModel role = roleContainer.getRole(roleName);
         return consentModel.isRoleGranted(role);