keycloak-uncached

Merge pull request #3662 from pedroigor/KEYCLOAK-4034 [KEYCLOAK-4034]

12/19/2016 4:49:10 PM

Changes

Details

diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProvider.java
index b1e668a..b0b9847 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProvider.java
@@ -17,6 +17,8 @@
  */
 package org.keycloak.authorization.policy.provider.aggregated;
 
+import java.util.List;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.evaluation.DecisionResultCollector;
@@ -26,21 +28,11 @@ import org.keycloak.authorization.policy.evaluation.Result;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 
-import java.util.List;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class AggregatePolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
-    private final AuthorizationProvider authorization;
-
-    public AggregatePolicyProvider(Policy policy, AuthorizationProvider authorization) {
-        this.policy = policy;
-        this.authorization = authorization;
-    }
-
     @Override
     public void evaluate(Evaluation evaluation) {
         //TODO: need to detect deep recursions
@@ -59,10 +51,12 @@ public class AggregatePolicyProvider implements PolicyProvider {
             }
         };
 
-        this.policy.getAssociatedPolicies().forEach(associatedPolicy -> {
-            PolicyProviderFactory providerFactory = authorization.getProviderFactory(associatedPolicy.getType());
-            PolicyProvider policyProvider = providerFactory.create(associatedPolicy, authorization);
-            policyProvider.evaluate(new DefaultEvaluation(evaluation.getPermission(), evaluation.getContext(), policy, associatedPolicy, decision));
+        Policy policy = evaluation.getPolicy();
+        AuthorizationProvider authorization = evaluation.getAuthorizationProvider();
+
+        policy.getAssociatedPolicies().forEach(associatedPolicy -> {
+            PolicyProvider policyProvider = authorization.getProvider(associatedPolicy.getType());
+            policyProvider.evaluate(new DefaultEvaluation(evaluation.getPermission(), evaluation.getContext(), policy, associatedPolicy, decision, authorization));
         });
 
         decision.onComplete();
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
index 9c7faad..3e86973 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyProviderFactory.java
@@ -19,7 +19,6 @@ package org.keycloak.authorization.policy.provider.aggregated;
 
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
@@ -32,6 +31,8 @@ import org.keycloak.models.KeycloakSessionFactory;
  */
 public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
 
+    private AggregatePolicyProvider provider = new AggregatePolicyProvider();
+
     @Override
     public String getName() {
         return "Aggregated";
@@ -43,8 +44,8 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new AggregatePolicyProvider(policy, authorization);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
index ec84bbc..5c778d8 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProvider.java
@@ -1,5 +1,7 @@
 package org.keycloak.authorization.policy.provider.client;
 
+import static org.keycloak.authorization.policy.provider.client.ClientPolicyProviderFactory.getClients;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.evaluation.Evaluation;
@@ -8,26 +10,19 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 
-import static org.keycloak.authorization.policy.provider.client.ClientPolicyProviderFactory.getClients;
-
 public class ClientPolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
-    private final AuthorizationProvider authorization;
-
-    public ClientPolicyProvider(Policy policy, AuthorizationProvider authorization) {
-        this.policy = policy;
-        this.authorization = authorization;
-    }
-
     @Override
     public void evaluate(Evaluation evaluation) {
+        Policy policy = evaluation.getPolicy();
         EvaluationContext context = evaluation.getContext();
-        String[] clients = getClients(this.policy);
+        String[] clients = getClients(policy);
+        AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
+        RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
 
         if (clients.length > 0) {
             for (String client : clients) {
-                ClientModel clientModel = getCurrentRealm().getClientById(client);
+                ClientModel clientModel = realm.getClientById(client);
                 if (context.getAttributes().containsValue("kc.client.id", clientModel.getClientId())) {
                     evaluation.grant();
                     return;
@@ -40,8 +35,4 @@ public class ClientPolicyProvider implements PolicyProvider {
     public void close() {
 
     }
-
-    private RealmModel getCurrentRealm() {
-        return this.authorization.getKeycloakSession().getContext().getRealm();
-    }
 }
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
index e800a5b..8cb0029 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/client/ClientPolicyProviderFactory.java
@@ -1,5 +1,9 @@
 package org.keycloak.authorization.policy.provider.client;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
@@ -8,18 +12,18 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
+import org.keycloak.authorization.store.ResourceServerStore;
+import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel.ClientRemovedEvent;
 import org.keycloak.util.JsonSerialization;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
 public class ClientPolicyProviderFactory implements PolicyProviderFactory {
 
+    private ClientPolicyProvider provider = new ClientPolicyProvider();
+
     @Override
     public String getName() {
         return "Client";
@@ -31,8 +35,8 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new ClientPolicyProvider(policy, authorization);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
@@ -56,31 +60,36 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory {
             if (event instanceof ClientRemovedEvent) {
                 KeycloakSession keycloakSession = ((ClientRemovedEvent) event).getKeycloakSession();
                 AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
-                PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
+                StoreFactory storeFactory = provider.getStoreFactory();
+                PolicyStore policyStore = storeFactory.getPolicyStore();
                 ClientModel removedClient = ((ClientRemovedEvent) event).getClient();
+                ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
+                ResourceServer resourceServer = resourceServerStore.findByClient(removedClient.getId());
 
-                policyStore.findByType(getId()).forEach(policy -> {
-                    List<String> clients = new ArrayList<>();
+                if (resourceServer != null) {
+                    policyStore.findByType(getId(), resourceServer.getId()).forEach(policy -> {
+                        List<String> clients = new ArrayList<>();
 
-                    for (String clientId : getClients(policy)) {
-                        if (!clientId.equals(removedClient.getId())) {
-                            clients.add(clientId);
+                        for (String clientId : getClients(policy)) {
+                            if (!clientId.equals(removedClient.getId())) {
+                                clients.add(clientId);
+                            }
                         }
-                    }
-
-                    try {
-                        if (clients.isEmpty()) {
-                            policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
-                                dependentPolicy.removeAssociatedPolicy(policy);
-                            });
-                            policyStore.delete(policy.getId());
-                        } else {
-                            policy.getConfig().put("clients", JsonSerialization.writeValueAsString(clients));
+
+                        try {
+                            if (clients.isEmpty()) {
+                                policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
+                                    dependentPolicy.removeAssociatedPolicy(policy);
+                                });
+                                policyStore.delete(policy.getId());
+                            } else {
+                                policy.getConfig().put("clients", JsonSerialization.writeValueAsString(clients));
+                            }
+                        } catch (IOException e) {
+                            throw new RuntimeException("Error while synchronizing clients with policy [" + policy.getName() + "].", e);
                         }
-                    } catch (IOException e) {
-                        throw new RuntimeException("Error while synchronizing clients with policy [" + policy.getName() + "].", e);
-                    }
-                });
+                    });
+                }
             }
         });
     }
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProvider.java
index eeeb3ea..f875731 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProvider.java
@@ -17,32 +17,34 @@
  */
 package org.keycloak.authorization.policy.provider.js;
 
-import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.policy.evaluation.Evaluation;
-import org.keycloak.authorization.policy.provider.PolicyProvider;
+import java.util.function.Supplier;
 
 import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.policy.evaluation.Evaluation;
+import org.keycloak.authorization.policy.provider.PolicyProvider;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class JSPolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
+    private Supplier<ScriptEngine> engineProvider;
 
-    public JSPolicyProvider(Policy policy) {
-        this.policy = policy;
+    public JSPolicyProvider(Supplier<ScriptEngine> engineProvider) {
+        this.engineProvider = engineProvider;
     }
 
     @Override
     public void evaluate(Evaluation evaluation) {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("nashorn");
+        ScriptEngine engine = engineProvider.get();
 
         engine.put("$evaluation", evaluation);
 
+        Policy policy = evaluation.getPolicy();
+
         try {
             engine.eval(policy.getConfig().get("code"));
         } catch (ScriptException e) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
index 8134d95..b4a5099 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
@@ -1,8 +1,12 @@
 package org.keycloak.authorization.policy.provider.js;
 
+import java.util.function.Supplier;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
@@ -15,6 +19,13 @@ import org.keycloak.models.KeycloakSessionFactory;
  */
 public class JSPolicyProviderFactory implements PolicyProviderFactory {
 
+    private JSPolicyProvider provider = new JSPolicyProvider(new Supplier<ScriptEngine>() {
+        @Override
+        public ScriptEngine get() {
+            return new ScriptEngineManager().getEngineByName("nashorn");
+        }
+    });
+
     @Override
     public String getName() {
         return "JavaScript";
@@ -26,8 +37,8 @@ public class JSPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new JSPolicyProvider(policy);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProvider.java
index c76a989..69e93fe 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProvider.java
@@ -17,7 +17,6 @@
  */
 package org.keycloak.authorization.policy.provider.resource;
 
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.evaluation.Evaluation;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 
@@ -26,7 +25,7 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
  */
 public class ResourcePolicyProvider implements PolicyProvider {
 
-    public ResourcePolicyProvider(Policy policy) {
+    public ResourcePolicyProvider() {
 
     }
 
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProviderFactory.java
index 8ea4800..d7a6b2b 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/resource/ResourcePolicyProviderFactory.java
@@ -2,7 +2,6 @@ package org.keycloak.authorization.policy.provider.resource;
 
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
@@ -15,6 +14,8 @@ import org.keycloak.models.KeycloakSessionFactory;
  */
 public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
 
+    private ResourcePolicyProvider provider = new ResourcePolicyProvider();
+
     @Override
     public String getName() {
         return "Resource-Based";
@@ -26,8 +27,8 @@ public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new ResourcePolicyProvider(policy);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
index 9fb9787..4aafedd 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProvider.java
@@ -17,6 +17,10 @@
  */
 package org.keycloak.authorization.policy.provider.role;
 
+import static org.keycloak.authorization.policy.provider.role.RolePolicyProviderFactory.getRoles;
+
+import java.util.Map;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.identity.Identity;
 import org.keycloak.authorization.model.Policy;
@@ -26,39 +30,26 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 
-import java.util.Map;
-
-import static org.keycloak.authorization.policy.provider.role.RolePolicyProviderFactory.getRoles;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class RolePolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
-    private final AuthorizationProvider authorization;
-
-    public RolePolicyProvider(Policy policy, AuthorizationProvider authorization) {
-        this.policy = policy;
-        this.authorization = authorization;
-    }
-
-    public RolePolicyProvider() {
-        this(null, null);
-    }
-
     @Override
     public void evaluate(Evaluation evaluation) {
-        Map<String, Object>[] roleIds = getRoles(this.policy);
+        Policy policy = evaluation.getPolicy();
+        Map<String, Object>[] roleIds = getRoles(policy);
+        AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
+        RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
 
         if (roleIds.length > 0) {
             Identity identity = evaluation.getContext().getIdentity();
 
             for (Map<String, Object> current : roleIds) {
-                RoleModel role = getCurrentRealm().getRoleById((String) current.get("id"));
+                RoleModel role = realm.getRoleById((String) current.get("id"));
 
                 if (role != null) {
-                    boolean hasRole = hasRole(identity, role);
+                    boolean hasRole = hasRole(identity, role, realm);
 
                     if (!hasRole && Boolean.valueOf(isRequired(current))) {
                         evaluation.deny();
@@ -75,19 +66,15 @@ public class RolePolicyProvider implements PolicyProvider {
         return (boolean) current.getOrDefault("required", false);
     }
 
-    private boolean hasRole(Identity identity, RoleModel role) {
+    private boolean hasRole(Identity identity, RoleModel role, RealmModel realm) {
         String roleName = role.getName();
         if (role.isClientRole()) {
-            ClientModel clientModel = getCurrentRealm().getClientById(role.getContainerId());
+            ClientModel clientModel = realm.getClientById(role.getContainerId());
             return identity.hasClientRole(clientModel.getClientId(), roleName);
         }
         return identity.hasRealmRole(roleName);
     }
 
-    private RealmModel getCurrentRealm() {
-        return this.authorization.getKeycloakSession().getContext().getRealm();
-    }
-
     @Override
     public void close() {
 
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
index 67de87a..33db2d5 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java
@@ -26,8 +26,13 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
+import org.keycloak.authorization.store.ResourceServerStore;
+import org.keycloak.authorization.store.StoreFactory;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
 import org.keycloak.models.RoleModel;
 import org.keycloak.util.JsonSerialization;
@@ -37,12 +42,15 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class RolePolicyProviderFactory implements PolicyProviderFactory {
 
+    private RolePolicyProvider provider = new RolePolicyProvider();
+
     @Override
     public String getName() {
         return "Role";
@@ -54,8 +62,8 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new RolePolicyProvider(policy, authorization);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
@@ -79,41 +87,61 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory {
             if (event instanceof RoleRemovedEvent) {
                 KeycloakSession keycloakSession = ((RoleRemovedEvent) event).getKeycloakSession();
                 AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
-                PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
+                StoreFactory storeFactory = provider.getStoreFactory();
+                PolicyStore policyStore = storeFactory.getPolicyStore();
                 RoleModel removedRole = ((RoleRemovedEvent) event).getRole();
+                RoleContainerModel container = removedRole.getContainer();
+                ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
+
+                if (container instanceof RealmModel) {
+                    RealmModel realm = (RealmModel) container;
+                    realm.getClients().forEach(clientModel -> updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore));
+                } else {
+                    ClientModel clientModel = (ClientModel) container;
+                    updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore);
+                }
+            }
+        });
+    }
 
-                policyStore.findByType(getId()).forEach(policy -> {
-                    List<Map> roles = new ArrayList<>();
+    private void updateResourceServer(ClientModel clientModel, RoleModel removedRole, ResourceServerStore resourceServerStore, PolicyStore policyStore) {
+        ResourceServer resourceServer = resourceServerStore.findByClient(clientModel.getId());
 
-                    for (Map<String,Object> role : getRoles(policy)) {
-                        if (!role.get("id").equals(removedRole.getId())) {
-                            Map updated = new HashMap();
-                            updated.put("id", role.get("id"));
-                            Object required = role.get("required");
-                            if (required != null) {
-                                updated.put("required", required);
-                            }
-                            roles.add(updated);
-                        }
-                    }
+        if (resourceServer != null) {
+            policyStore.findByType(getId(), resourceServer.getId()).forEach(policy -> {
+                List<Map> roles = new ArrayList<>();
 
-                    try {
-                        if (roles.isEmpty()) {
-                            policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
-                                dependentPolicy.removeAssociatedPolicy(policy);
-                            });
-                            policyStore.delete(policy.getId());
-                        } else {
-                            Map<String, String> config = policy.getConfig();
-                            config.put("roles", JsonSerialization.writeValueAsString(roles));
-                            policy.setConfig(config);
+                for (Map<String,Object> role : getRoles(policy)) {
+                    if (!role.get("id").equals(removedRole.getId())) {
+                        Map updated = new HashMap();
+                        updated.put("id", role.get("id"));
+                        Object required = role.get("required");
+                        if (required != null) {
+                            updated.put("required", required);
                         }
-                    } catch (IOException e) {
-                        throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
+                        roles.add(updated);
                     }
-                });
-            }
-        });
+                }
+
+                try {
+                    if (roles.isEmpty()) {
+                        policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
+                            dependentPolicy.removeAssociatedPolicy(policy);
+                            if (dependentPolicy.getAssociatedPolicies().isEmpty()) {
+                                policyStore.delete(dependentPolicy.getId());
+                            }
+                        });
+                        policyStore.delete(policy.getId());
+                    } else {
+                        Map<String, String> config = policy.getConfig();
+                        config.put("roles", JsonSerialization.writeValueAsString(roles));
+                        policy.setConfig(config);
+                    }
+                } catch (IOException e) {
+                    throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
+                }
+            });
+        }
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProvider.java
index 5c10cc3..0a8cf85 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProvider.java
@@ -17,7 +17,6 @@
  */
 package org.keycloak.authorization.policy.provider.scope;
 
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.evaluation.Evaluation;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 
@@ -26,12 +25,6 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
  */
 public class ScopePolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
-
-    public ScopePolicyProvider(Policy policy) {
-        this.policy = policy;
-    }
-
     @Override
     public void evaluate(Evaluation evaluation) {
     }
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProviderFactory.java
index 6ed0cd5..0678eb3 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/scope/ScopePolicyProviderFactory.java
@@ -2,7 +2,6 @@ package org.keycloak.authorization.policy.provider.scope;
 
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
@@ -15,6 +14,8 @@ import org.keycloak.models.KeycloakSessionFactory;
  */
 public class ScopePolicyProviderFactory implements PolicyProviderFactory {
 
+    private ScopePolicyProvider provider = new ScopePolicyProvider();
+
     @Override
     public String getName() {
         return "Scope-Based";
@@ -26,8 +27,8 @@ public class ScopePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new ScopePolicyProvider(policy);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
index 84ba1a2..7ce4c6e 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
@@ -17,14 +17,14 @@
  */
 package org.keycloak.authorization.policy.provider.time;
 
-import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.policy.evaluation.Evaluation;
-import org.keycloak.authorization.policy.provider.PolicyProvider;
-
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.policy.evaluation.Evaluation;
+import org.keycloak.authorization.policy.provider.PolicyProvider;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -32,51 +32,51 @@ public class TimePolicyProvider implements PolicyProvider {
 
     static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd hh:mm:ss";
 
-    private final Policy policy;
     private final SimpleDateFormat dateFormat;
     private final Date currentDate;
 
-    public TimePolicyProvider(Policy policy) {
-        this.policy = policy;
+    public TimePolicyProvider() {
         this.dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
         this.currentDate = new Date();
     }
 
     @Override
     public void evaluate(Evaluation evaluation) {
+        Policy policy = evaluation.getPolicy();
+
         try {
-            String notBefore = this.policy.getConfig().get("nbf");
-            if (notBefore != null) {
+            String notBefore = policy.getConfig().get("nbf");
+            if (notBefore != null && !"".equals(notBefore)) {
                 if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
                     evaluation.deny();
                     return;
                 }
             }
 
-            String notOnOrAfter = this.policy.getConfig().get("noa");
-            if (notOnOrAfter != null) {
+            String notOnOrAfter = policy.getConfig().get("noa");
+            if (notOnOrAfter != null && !"".equals(notOnOrAfter)) {
                 if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
                     evaluation.deny();
                     return;
                 }
             }
 
-            if (isInvalid(Calendar.DAY_OF_MONTH, "dayMonth")
-                    || isInvalid(Calendar.MONTH, "month")
-                    || isInvalid(Calendar.YEAR, "year")
-                    || isInvalid(Calendar.HOUR_OF_DAY, "hour")
-                    || isInvalid(Calendar.MINUTE, "minute")) {
+            if (isInvalid(Calendar.DAY_OF_MONTH, "dayMonth", policy)
+                    || isInvalid(Calendar.MONTH, "month", policy)
+                    || isInvalid(Calendar.YEAR, "year", policy)
+                    || isInvalid(Calendar.HOUR_OF_DAY, "hour", policy)
+                    || isInvalid(Calendar.MINUTE, "minute", policy)) {
                 evaluation.deny();
                 return;
             }
 
             evaluation.grant();
         } catch (Exception e) {
-            throw new RuntimeException("Could not evaluate time-based policy [" + this.policy.getName() + "].", e);
+            throw new RuntimeException("Could not evaluate time-based policy [" + policy.getName() + "].", e);
         }
     }
 
-    private boolean isInvalid(int timeConstant, String configName) {
+    private boolean isInvalid(int timeConstant, String configName, Policy policy) {
         Calendar calendar = Calendar.getInstance();
 
         calendar.setTime(this.currentDate);
@@ -87,9 +87,9 @@ public class TimePolicyProvider implements PolicyProvider {
             dateField++;
         }
 
-        String start = this.policy.getConfig().get(configName);
+        String start = policy.getConfig().get(configName);
         if (start != null) {
-            String end = this.policy.getConfig().get(configName + "End");
+            String end = policy.getConfig().get(configName + "End");
             if (end != null) {
                 if (dateField < Integer.parseInt(start)  || dateField > Integer.parseInt(end)) {
                     return true;
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
index efe3cd2..94c5aad 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
@@ -2,7 +2,6 @@ package org.keycloak.authorization.policy.provider.time;
 
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
@@ -15,6 +14,8 @@ import org.keycloak.models.KeycloakSessionFactory;
  */
 public class TimePolicyProviderFactory implements PolicyProviderFactory {
 
+    private TimePolicyProvider provider = new TimePolicyProvider();
+
     @Override
     public String getName() {
         return "Time";
@@ -26,8 +27,8 @@ public class TimePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new TimePolicyProvider(policy);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
index a6fc0a4..2f77106 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProvider.java
@@ -29,16 +29,11 @@ import static org.keycloak.authorization.policy.provider.user.UserPolicyProvider
  */
 public class UserPolicyProvider implements PolicyProvider {
 
-    private final Policy policy;
-
-    public UserPolicyProvider(Policy policy) {
-        this.policy = policy;
-    }
-
     @Override
     public void evaluate(Evaluation evaluation) {
+        Policy policy = evaluation.getPolicy();
         EvaluationContext context = evaluation.getContext();
-        String[] userIds = getUsers(this.policy);
+        String[] userIds = getUsers(policy);
 
         if (userIds.length > 0) {
             for (String userId : userIds) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
index fdeeac0..09345ec 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java
@@ -18,6 +18,10 @@
 
 package org.keycloak.authorization.policy.provider.user;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
@@ -26,21 +30,22 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
+import org.keycloak.authorization.store.ResourceServerStore;
+import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.UserRemovedEvent;
 import org.keycloak.util.JsonSerialization;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class UserPolicyProviderFactory implements PolicyProviderFactory {
 
+    private UserPolicyProvider provider = new UserPolicyProvider();
+
     @Override
     public String getName() {
         return "User";
@@ -52,8 +57,8 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new UserPolicyProvider(policy);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
@@ -77,29 +82,40 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory {
             if (event instanceof UserRemovedEvent) {
                 KeycloakSession keycloakSession = ((UserRemovedEvent) event).getKeycloakSession();
                 AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
-                PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
+                StoreFactory storeFactory = provider.getStoreFactory();
+                PolicyStore policyStore = storeFactory.getPolicyStore();
                 UserModel removedUser = ((UserRemovedEvent) event).getUser();
-
-                policyStore.findByType(getId()).forEach(policy -> {
-                    List<String> users = new ArrayList<>();
-
-                    for (String userId : getUsers(policy)) {
-                        if (!userId.equals(removedUser.getId())) {
-                            users.add(userId);
-                        }
-                    }
-
-                    try {
-                        if (users.isEmpty()) {
-                            policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
-                                dependentPolicy.removeAssociatedPolicy(policy);
-                            });
-                            policyStore.delete(policy.getId());
-                        } else {
-                            policy.getConfig().put("users", JsonSerialization.writeValueAsString(users));
-                        }
-                    } catch (IOException e) {
-                        throw new RuntimeException("Error while synchronizing users with policy [" + policy.getName() + "].", e);
+                RealmModel realm = ((UserRemovedEvent) event).getRealm();
+                ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
+                realm.getClients().forEach(clientModel -> {
+                    ResourceServer resourceServer = resourceServerStore.findByClient(clientModel.getId());
+
+                    if (resourceServer != null) {
+                        policyStore.findByType(getId(), resourceServer.getId()).forEach(policy -> {
+                            List<String> users = new ArrayList<>();
+
+                            for (String userId : getUsers(policy)) {
+                                if (!userId.equals(removedUser.getId())) {
+                                    users.add(userId);
+                                }
+                            }
+
+                            try {
+                                if (users.isEmpty()) {
+                                    policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
+                                        dependentPolicy.removeAssociatedPolicy(policy);
+                                        if (dependentPolicy.getAssociatedPolicies().isEmpty()) {
+                                            policyStore.delete(dependentPolicy.getId());
+                                        }
+                                    });
+                                    policyStore.delete(policy.getId());
+                                } else {
+                                    policy.getConfig().put("users", JsonSerialization.writeValueAsString(users));
+                                }
+                            } catch (IOException e) {
+                                throw new RuntimeException("Error while synchronizing users with policy [" + policy.getName() + "].", e);
+                            }
+                        });
                     }
                 });
             }
diff --git a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProvider.java b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProvider.java
index c53e361..77023f5 100644
--- a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProvider.java
+++ b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProvider.java
@@ -17,6 +17,9 @@
  */
 package org.keycloak.authorization.policy.provider.drools;
 
+import java.util.function.Function;
+
+import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.evaluation.Evaluation;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 
@@ -25,15 +28,15 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
  */
 public class DroolsPolicyProvider implements PolicyProvider {
 
-    private final DroolsPolicy policy;
+    private final Function<Policy, DroolsPolicy> policy;
 
-    public DroolsPolicyProvider(DroolsPolicy policy) {
-        this.policy = policy;
+    public DroolsPolicyProvider(Function<Policy, DroolsPolicy> policyProvider) {
+        this.policy = policyProvider;
     }
 
     @Override
-    public void evaluate(Evaluation evaluationt) {
-        this.policy.evaluate(evaluationt);
+    public void evaluate(Evaluation evaluation) {
+        policy.apply(evaluation.getPolicy()).evaluate(evaluation);
     }
 
     @Override
diff --git a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProviderFactory.java b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProviderFactory.java
index b3305ae..74ed89d 100644
--- a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProviderFactory.java
+++ b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyProviderFactory.java
@@ -1,5 +1,9 @@
 package org.keycloak.authorization.policy.provider.drools;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
@@ -9,24 +13,25 @@ import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.utils.PostMigrationEvent;
-import org.keycloak.provider.ProviderEvent;
-import org.keycloak.provider.ProviderEventListener;
-import org.keycloak.provider.ProviderFactory;
 import org.kie.api.KieServices;
 import org.kie.api.KieServices.Factory;
 import org.kie.api.runtime.KieContainer;
 
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
 
     private KieServices ks;
-    private final Map<String, DroolsPolicy> containers = new HashMap<>();
+    private final Map<String, DroolsPolicy> containers = Collections.synchronizedMap(new HashMap<>());
+    private DroolsPolicyProvider provider = new DroolsPolicyProvider(policy -> {
+        if (!containers.containsKey(policy.getId())) {
+            synchronized (containers) {
+                update(policy);
+            }
+        }
+        return containers.get(policy.getId());
+    });
 
     @Override
     public String getName() {
@@ -39,12 +44,8 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        if (!this.containers.containsKey(policy.getId())) {
-            update(policy);
-        }
-
-        return new DroolsPolicyProvider(this.containers.get(policy.getId()));
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return provider;
     }
 
     @Override
@@ -64,19 +65,6 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
 
     @Override
     public void postInit(KeycloakSessionFactory factory) {
-        factory.register(new ProviderEventListener() {
-
-            @Override
-            public void onEvent(ProviderEvent event) {
-                // Ensure the initialization is done after DB upgrade is finished
-                if (event instanceof PostMigrationEvent) {
-                    ProviderFactory<AuthorizationProvider> providerFactory = factory.getProviderFactory(AuthorizationProvider.class);
-                    AuthorizationProvider authorization = providerFactory.create(factory.create());
-                    authorization.getStoreFactory().getPolicyStore().findByType(getId()).forEach(DroolsPolicyProviderFactory.this::update);
-                }
-            }
-
-        });
     }
 
     @Override
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
index 9a51031..dc04991 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/PolicyRepresentation.java
@@ -16,11 +16,7 @@
  */
 package org.keycloak.representations.idm.authorization;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
-
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -36,9 +32,6 @@ public class PolicyRepresentation {
     private Logic logic = Logic.POSITIVE;
     private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
     private Map<String, String> config = new HashMap();
-    private List<PolicyRepresentation> dependentPolicies;
-    @JsonInclude(JsonInclude.Include.NON_EMPTY)
-    private List<PolicyRepresentation> associatedPolicies = new ArrayList<>();
 
     public String getId() {
         return this.id;
@@ -96,14 +89,6 @@ public class PolicyRepresentation {
         this.description = description;
     }
 
-    public List<PolicyRepresentation> getAssociatedPolicies() {
-        return associatedPolicies;
-    }
-
-    public void setAssociatedPolicies(List<PolicyRepresentation> associatedPolicies) {
-        this.associatedPolicies = associatedPolicies;
-    }
-
     @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
@@ -116,12 +101,4 @@ public class PolicyRepresentation {
     public int hashCode() {
         return Objects.hash(getId());
     }
-
-    public void setDependentPolicies(List<PolicyRepresentation> dependentPolicies) {
-        this.dependentPolicies = dependentPolicies;
-    }
-
-    public List<PolicyRepresentation> getDependentPolicies() {
-        return this.dependentPolicies;
-    }
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/ResourceRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/ResourceRepresentation.java
index 8f3c795..86f6f98 100644
--- a/core/src/main/java/org/keycloak/representations/idm/authorization/ResourceRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/ResourceRepresentation.java
@@ -16,14 +16,14 @@
  */
 package org.keycloak.representations.idm.authorization;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
 import java.net.URI;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
-import java.util.function.Predicate;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 /**
  * <p>One or more resources that the resource server manages as a set of protected resources.
@@ -159,18 +159,6 @@ public class ResourceRepresentation {
         this.owner = owner;
     }
 
-    public List<PolicyRepresentation> getPolicies() {
-        return this.policies;
-    }
-
-    public void setPolicies(List<PolicyRepresentation> policies) {
-        this.policies = policies;
-    }
-
-    <T> T test(Predicate<T> t) {
-        return null;
-    }
-
     public void setTypedScopes(List<ScopeRepresentation> typedScopes) {
         this.typedScopes = typedScopes;
     }
@@ -178,4 +166,15 @@ public class ResourceRepresentation {
     public List<ScopeRepresentation> getTypedScopes() {
         return typedScopes;
     }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ResourceRepresentation scope = (ResourceRepresentation) o;
+        return Objects.equals(getName(), scope.getName());
+    }
+
+    public int hashCode() {
+        return Objects.hash(getName());
+    }
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PolicyResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PolicyResource.java
index 9a45045..28202f5 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PolicyResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PolicyResource.java
@@ -16,16 +16,21 @@
  */
 package org.keycloak.admin.client.resource;
 
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -42,4 +47,28 @@ public interface PolicyResource {
 
     @DELETE
     void remove();
+
+    @Path("/associatedPolicies")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    List<PolicyRepresentation> associatedPolicies();
+
+    @Path("/dependentPolicies")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    List<PolicyRepresentation> dependentPolicies();
+
+    @Path("/scopes")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    List<ScopeRepresentation> scopes();
+
+    @Path("/resources")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    List<ResourceRepresentation> resources();
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceResource.java
index 834cb06..28e57a7 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceResource.java
@@ -16,13 +16,17 @@
  */
 package org.keycloak.admin.client.resource;
 
+import java.util.List;
+
 import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
@@ -42,4 +46,10 @@ public interface ResourceResource {
 
     @DELETE
     void remove();
+
+    @Path("permissions")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    List<PolicyRepresentation> permissions();
 }
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopeResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopeResource.java
index 6975574..87b285b 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopeResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ResourceScopeResource.java
@@ -16,13 +16,17 @@
  */
 package org.keycloak.admin.client.resource;
 
+import java.util.List;
+
 import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
@@ -42,4 +46,9 @@ public interface ResourceScopeResource {
 
     @DELETE
     void remove();
+
+    @Path("/permissions")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    List<PolicyRepresentation> permissions();
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
index b503bce..3914c68 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
@@ -18,6 +18,17 @@
 
 package org.keycloak.models.authorization.infinispan;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
 import org.infinispan.Cache;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
@@ -29,17 +40,10 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.authorization.infinispan.InfinispanStoreFactoryProvider.CacheTransaction;
 import org.keycloak.models.authorization.infinispan.entities.CachedPolicy;
+import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
 import org.keycloak.representations.idm.authorization.DecisionStrategy;
 import org.keycloak.representations.idm.authorization.Logic;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.stream.Collectors;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -47,41 +51,58 @@ public class CachedPolicyStore implements PolicyStore {
 
     private static final String POLICY_ID_CACHE_PREFIX = "policy-id-";
 
-    private final Cache<String, List> cache;
+    private final Cache<String, List<CachedPolicy>> cache;
     private final KeycloakSession session;
     private final CacheTransaction transaction;
+    private final List<String> cacheKeys;
     private StoreFactory storeFactory;
     private PolicyStore delegate;
+    private CachedStoreFactoryProvider cachedStoreFactory;
 
-    public CachedPolicyStore(KeycloakSession session, CacheTransaction transaction) {
+    public CachedPolicyStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
         this.transaction = transaction;
         InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
         this.cache = provider.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
+        cacheKeys = new ArrayList<>();
+        cacheKeys.add("findByResource");
+        cacheKeys.add("findByResourceType");
+        cacheKeys.add("findByScopeIds");
+        cacheKeys.add("findByType");
+        this.storeFactory = storeFactory;
     }
 
     @Override
     public Policy create(String name, String type, ResourceServer resourceServer) {
         Policy policy = getDelegate().create(name, type, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()));
+        String id = policy.getId();
 
-        this.transaction.whenRollback(() -> cache.remove(getCacheKeyForPolicy(policy.getId())));
+        this.transaction.whenCommit(() -> {
+            cache.remove(getCacheKeyForPolicy(id));
+            invalidateCache(resourceServer.getId());
+        });
 
         return createAdapter(new CachedPolicy(policy));
     }
 
     @Override
     public void delete(String id) {
+        Policy policy = findById(id, null);
+        ResourceServer resourceServer = policy.getResourceServer();
         getDelegate().delete(id);
-        this.transaction.whenCommit(() -> cache.remove(getCacheKeyForPolicy(id)));
+        this.transaction.whenCommit(() -> {
+            cache.remove(getCacheKeyForPolicy(id));
+            invalidateCache(resourceServer.getId());
+        });
     }
 
     @Override
-    public Policy findById(String id) {
+    public Policy findById(String id, String resourceServerId) {
         String cacheKeyForPolicy = getCacheKeyForPolicy(id);
         List<CachedPolicy> cached = this.cache.get(cacheKeyForPolicy);
 
         if (cached == null) {
-            Policy policy = getDelegate().findById(id);
+            Policy policy = getDelegate().findById(id, resourceServerId);
 
             if (policy != null) {
                 return createAdapter(updatePolicyCache(policy));
@@ -100,7 +121,7 @@ public class CachedPolicyStore implements PolicyStore {
 
     @Override
     public List<Policy> findByResourceServer(String resourceServerId) {
-        return getDelegate().findByResourceServer(resourceServerId).stream().map(policy -> findById(policy.getId())).collect(Collectors.toList());
+        return getDelegate().findByResourceServer(resourceServerId);
     }
 
     @Override
@@ -109,88 +130,49 @@ public class CachedPolicyStore implements PolicyStore {
     }
 
     @Override
-    public List<Policy> findByResource(String resourceId) {
-        List<Policy> cache = new ArrayList<>();
-
-        for (Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
-
-            if (cacheKey.startsWith(POLICY_ID_CACHE_PREFIX)) {
-                List<CachedPolicy> value = (List<CachedPolicy>) entry.getValue();
-                CachedPolicy policy = value.get(0);
-
-                if (policy.getResourcesIds().contains(resourceId)) {
-                    cache.add(findById(policy.getId()));
-                }
-            }
-        }
-
-        if (cache.isEmpty()) {
-            getDelegate().findByResource(resourceId).forEach(policy -> cache.add(findById(updatePolicyCache(policy).getId())));
-        }
-
-        return cache;
+    public List<Policy> findByResource(String resourceId, String resourceServerId) {
+        return cacheResult(new StringBuilder("findByResource").append(resourceServerId).append(resourceId).toString(), () -> getDelegate().findByResource(resourceId, resourceServerId));
     }
 
     @Override
     public List<Policy> findByResourceType(String resourceType, String resourceServerId) {
-        List<Policy> cache = new ArrayList<>();
-
-        for (Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
-
-            if (cacheKey.startsWith(POLICY_ID_CACHE_PREFIX)) {
-                List<CachedPolicy> value = (List<CachedPolicy>) entry.getValue();
-                CachedPolicy policy = value.get(0);
-
-                if (policy.getResourceServerId().equals(resourceServerId) && policy.getConfig().getOrDefault("defaultResourceType", "").equals(resourceType)) {
-                    cache.add(findById(policy.getId()));
-                }
-            }
-        }
-
-        if (cache.isEmpty()) {
-            getDelegate().findByResourceType(resourceType, resourceServerId).forEach(policy -> cache.add(findById(updatePolicyCache(policy).getId())));
-        }
-
-        return cache;
+        return cacheResult(new StringBuilder("findByResourceType").append(resourceServerId).append(resourceType).toString(), () -> getDelegate().findByResourceType(resourceType, resourceServerId));
     }
 
     @Override
     public List<Policy> findByScopeIds(List<String> scopeIds, String resourceServerId) {
-        List<Policy> cache = new ArrayList<>();
-
-        for (Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
+        List<Policy> policies = new ArrayList<>();
 
-            if (cacheKey.startsWith(POLICY_ID_CACHE_PREFIX)) {
-                List<CachedPolicy> value = (List<CachedPolicy>) entry.getValue();
-                CachedPolicy policy = value.get(0);
-
-                for (String scopeId : policy.getScopesIds()) {
-                    if (scopeIds.contains(scopeId)) {
-                        cache.add(findById(policy.getId()));
-                        break;
-                    }
-                }
-            }
+        for (String scopeId : scopeIds) {
+            policies.addAll(cacheResult(new StringBuilder("findByScopeIds").append(resourceServerId).append(scopeId).toString(), () -> getDelegate().findByScopeIds(Arrays.asList(scopeId), resourceServerId)));
         }
 
-        if (cache.isEmpty()) {
-            getDelegate().findByScopeIds(scopeIds, resourceServerId).forEach(policy -> cache.add(findById(updatePolicyCache(policy).getId())));
-        }
+        return policies;
+    }
 
-        return cache;
+    @Override
+    public List<Policy> findByType(String type, String resourceServerId) {
+        return cacheResult(new StringBuilder("findByType").append(resourceServerId).append(type).toString(), () -> getDelegate().findByType(type, resourceServerId));
     }
 
     @Override
-    public List<Policy> findByType(String type) {
-        return getDelegate().findByType(type).stream().map(policy -> findById(policy.getId())).collect(Collectors.toList());
+    public List<Policy> findDependentPolicies(String id, String resourceServerId) {
+        return getDelegate().findDependentPolicies(id, resourceServerId);
     }
 
     @Override
-    public List<Policy> findDependentPolicies(String id) {
-        return getDelegate().findDependentPolicies(id).stream().map(policy -> findById(policy.getId())).collect(Collectors.toList());
+    public void notifyChange(Object cached) {
+        String resourceServerId;
+
+        if (Resource.class.isInstance(cached)) {
+            resourceServerId = ((Resource) cached).getResourceServer().getId();
+        } else if (Scope.class.isInstance(cached)){
+            resourceServerId = ((Scope) cached).getResourceServer().getId();
+        } else {
+            throw new RuntimeException("Unexpected notification [" + cached + "]");
+        }
+
+        invalidateCache(resourceServerId);
     }
 
     private String getCacheKeyForPolicy(String policyId) {
@@ -198,10 +180,6 @@ public class CachedPolicyStore implements PolicyStore {
     }
 
     private StoreFactory getStoreFactory() {
-        if (this.storeFactory == null) {
-            this.storeFactory = this.session.getProvider(StoreFactory.class);
-        }
-
         return this.storeFactory;
     }
 
@@ -216,6 +194,9 @@ public class CachedPolicyStore implements PolicyStore {
     private Policy createAdapter(CachedPolicy cached) {
         return new Policy() {
 
+            private Set<Scope> scopes;
+            private Set<Resource> resources;
+            private Set<Policy> associatedPolicies;
             private Policy updated;
 
             @Override
@@ -285,54 +266,56 @@ public class CachedPolicyStore implements PolicyStore {
 
             @Override
             public ResourceServer getResourceServer() {
-                return getStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
+                return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
             }
 
             @Override
             public void addScope(Scope scope) {
-                getDelegateForUpdate().addScope(getStoreFactory().getScopeStore().findById(scope.getId()));
+                getDelegateForUpdate().addScope(getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId()));
                 cached.addScope(scope);
             }
 
             @Override
             public void removeScope(Scope scope) {
-                getDelegateForUpdate().removeScope(getStoreFactory().getScopeStore().findById(scope.getId()));
+                getDelegateForUpdate().removeScope(scope);
                 cached.removeScope(scope);
             }
 
             @Override
             public void addAssociatedPolicy(Policy associatedPolicy) {
-                getDelegateForUpdate().addAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId()));
+                getDelegateForUpdate().addAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId(), cached.getResourceServerId()));
                 cached.addAssociatedPolicy(associatedPolicy);
             }
 
             @Override
             public void removeAssociatedPolicy(Policy associatedPolicy) {
-                getDelegateForUpdate().removeAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId()));
+                getDelegateForUpdate().removeAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId(), cached.getResourceServerId()));
                 cached.removeAssociatedPolicy(associatedPolicy);
             }
 
             @Override
             public void addResource(Resource resource) {
-                getDelegateForUpdate().addResource(getStoreFactory().getResourceStore().findById(resource.getId()));
+                getDelegateForUpdate().addResource(getStoreFactory().getResourceStore().findById(resource.getId(), cached.getResourceServerId()));
                 cached.addResource(resource);
             }
 
             @Override
             public void removeResource(Resource resource) {
-                getDelegateForUpdate().removeResource(getStoreFactory().getResourceStore().findById(resource.getId()));
+                getDelegateForUpdate().removeResource(getStoreFactory().getResourceStore().findById(resource.getId(), cached.getResourceServerId()));
                 cached.removeResource(resource);
             }
 
             @Override
             public Set<Policy> getAssociatedPolicies() {
-                Set<Policy> associatedPolicies = new HashSet<>();
+                if (associatedPolicies == null) {
+                    associatedPolicies = new HashSet<>();
 
-                for (String id : cached.getAssociatedPoliciesIds()) {
-                    Policy cached = findById(id);
+                    for (String id : cached.getAssociatedPoliciesIds()) {
+                        Policy policy = findById(id, cached.getResourceServerId());
 
-                    if (cached != null) {
-                        associatedPolicies.add(cached);
+                        if (policy != null) {
+                            associatedPolicies.add(policy);
+                        }
                     }
                 }
 
@@ -341,13 +324,15 @@ public class CachedPolicyStore implements PolicyStore {
 
             @Override
             public Set<Resource> getResources() {
-                Set<Resource> resources = new HashSet<>();
+                if (resources == null) {
+                    resources = new HashSet<>();
 
-                for (String id : cached.getResourcesIds()) {
-                    Resource cached = getStoreFactory().getResourceStore().findById(id);
+                    for (String id : cached.getResourcesIds()) {
+                        Resource resource = getCachedStoreFactory().getResourceStore().findById(id, cached.getResourceServerId());
 
-                    if (cached != null) {
-                        resources.add(cached);
+                        if (resource != null) {
+                            resources.add(resource);
+                        }
                     }
                 }
 
@@ -356,13 +341,15 @@ public class CachedPolicyStore implements PolicyStore {
 
             @Override
             public Set<Scope> getScopes() {
-                Set<Scope> scopes = new HashSet<>();
+                if (scopes == null) {
+                    scopes = new HashSet<>();
 
-                for (String id : cached.getScopesIds()) {
-                    Scope cached = getStoreFactory().getScopeStore().findById(id);
+                    for (String id : cached.getScopesIds()) {
+                        Scope scope = getCachedStoreFactory().getScopeStore().findById(id, cached.getResourceServerId());
 
-                    if (cached != null) {
-                        scopes.add(cached);
+                        if (scope != null) {
+                            scopes.add(scope);
+                        }
                     }
                 }
 
@@ -392,9 +379,12 @@ public class CachedPolicyStore implements PolicyStore {
 
             private Policy getDelegateForUpdate() {
                 if (this.updated == null) {
-                    this.updated = getDelegate().findById(getId());
+                    this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
-                    transaction.whenCommit(() -> cache.remove(getCacheKeyForPolicy(getId())));
+                    transaction.whenCommit(() -> {
+                        cache.remove(getCacheKeyForPolicy(getId()));
+                        invalidateCache(cached.getResourceServerId());
+                    });
                 }
 
                 return this.updated;
@@ -402,9 +392,16 @@ public class CachedPolicyStore implements PolicyStore {
         };
     }
 
+    private CachedStoreFactoryProvider getCachedStoreFactory() {
+        if (cachedStoreFactory == null) {
+            cachedStoreFactory = session.getProvider(CachedStoreFactoryProvider.class);
+        }
+        return cachedStoreFactory;
+    }
+
     private CachedPolicy updatePolicyCache(Policy policy) {
         CachedPolicy cached = new CachedPolicy(policy);
-        List<Policy> cache = new ArrayList<>();
+        List<CachedPolicy> cache = new ArrayList<>();
 
         cache.add(cached);
 
@@ -413,4 +410,25 @@ public class CachedPolicyStore implements PolicyStore {
         return cached;
     }
 
+    private void invalidateCache(String resourceServerId) {
+        cacheKeys.forEach(cacheKey -> cache.keySet().stream().filter(key -> key.startsWith(cacheKey + resourceServerId)).forEach(cache::remove));
+    }
+
+    private List<Policy> cacheResult(String key, Supplier<List<Policy>> provider) {
+        List<CachedPolicy> cached = cache.computeIfAbsent(key, (Function<String, List<CachedPolicy>>) o -> {
+            List<Policy> result = provider.get();
+
+            if (result.isEmpty()) {
+                return Collections.emptyList();
+            }
+
+            return result.stream().map(policy -> new CachedPolicy(policy)).collect(Collectors.toList());
+        });
+
+        if (cached == null) {
+            return Collections.emptyList();
+        }
+
+        return cached.stream().map(cachedPolicy -> createAdapter(cachedPolicy)).collect(Collectors.toList());
+    }
 }
\ No newline at end of file
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
index 2685135..ed98500 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceServerStore.java
@@ -18,6 +18,10 @@
 
 package org.keycloak.models.authorization.infinispan;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import org.infinispan.Cache;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.store.ResourceServerStore;
@@ -28,16 +32,13 @@ import org.keycloak.models.authorization.infinispan.InfinispanStoreFactoryProvid
 import org.keycloak.models.authorization.infinispan.entities.CachedResourceServer;
 import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class CachedResourceServerStore implements ResourceServerStore {
 
     private static final String RS_ID_CACHE_PREFIX = "rs-id-";
+    private static final String RS_CLIENT_ID_CACHE_PREFIX = "rs-client-id-";
 
     private final KeycloakSession session;
     private final CacheTransaction transaction;
@@ -45,11 +46,12 @@ public class CachedResourceServerStore implements ResourceServerStore {
     private ResourceServerStore delegate;
     private final Cache<String, List> cache;
 
-    public CachedResourceServerStore(KeycloakSession session, CacheTransaction transaction) {
+    public CachedResourceServerStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
         this.transaction = transaction;
         InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
         this.cache = provider.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
+        this.storeFactory = storeFactory;
     }
 
     @Override
@@ -64,7 +66,14 @@ public class CachedResourceServerStore implements ResourceServerStore {
     @Override
     public void delete(String id) {
         getDelegate().delete(id);
-        this.transaction.whenCommit(() -> this.cache.remove(getCacheKeyForResourceServer(id)));
+        this.transaction.whenCommit(() -> {
+            List<CachedResourceServer> servers = cache.remove(getCacheKeyForResourceServer(id));
+
+            if (servers != null) {
+                CachedResourceServer entry = servers.get(0);
+                cache.remove(getCacheKeyForResourceServerClientId(entry.getClientId()));
+            }
+        });
     }
 
     @Override
@@ -87,32 +96,31 @@ public class CachedResourceServerStore implements ResourceServerStore {
 
     @Override
     public ResourceServer findByClient(String id) {
-        for (Map.Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
+        String cacheKeyForResourceServer = getCacheKeyForResourceServerClientId(id);
+        List<String> cached = this.cache.get(cacheKeyForResourceServer);
 
-            if (cacheKey.startsWith(RS_ID_CACHE_PREFIX)) {
-                List<ResourceServer> cache = (List<ResourceServer>) entry.getValue();
-                ResourceServer resourceServer = cache.get(0);
+        if (cached == null) {
+            ResourceServer resourceServer = getDelegate().findByClient(id);
 
-                if (resourceServer.getClientId().equals(id)) {
-                    return findById(resourceServer.getId());
-                }
+            if (resourceServer != null) {
+                cache.put(cacheKeyForResourceServer, Arrays.asList(resourceServer.getId()));
+                return findById(resourceServer.getId());
             }
-        }
 
-        ResourceServer resourceServer = getDelegate().findByClient(id);
-
-        if (resourceServer != null) {
-            return findById(updateResourceServerCache(resourceServer).getId());
+            return null;
         }
 
-        return null;
+        return findById(cached.get(0));
     }
 
     private String getCacheKeyForResourceServer(String id) {
         return RS_ID_CACHE_PREFIX + id;
     }
 
+    private String getCacheKeyForResourceServerClientId(String id) {
+        return RS_CLIENT_ID_CACHE_PREFIX + id;
+    }
+
     private ResourceServerStore getDelegate() {
         if (this.delegate == null) {
             this.delegate = getStoreFactory().getResourceServerStore();
@@ -122,10 +130,6 @@ public class CachedResourceServerStore implements ResourceServerStore {
     }
 
     private StoreFactory getStoreFactory() {
-        if (this.storeFactory == null) {
-            this.storeFactory = session.getProvider(StoreFactory.class);
-        }
-
         return this.storeFactory;
     }
     private ResourceServer createAdapter(ResourceServer cached) {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
index 8696d8d..6ebac83 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
@@ -18,6 +18,16 @@
 
 package org.keycloak.models.authorization.infinispan;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
 import org.infinispan.Cache;
 import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
@@ -28,14 +38,7 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.authorization.infinispan.InfinispanStoreFactoryProvider.CacheTransaction;
 import org.keycloak.models.authorization.infinispan.entities.CachedResource;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.stream.Collectors;
+import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -43,60 +46,63 @@ import java.util.stream.Collectors;
 public class CachedResourceStore implements ResourceStore {
 
     private static final String RESOURCE_ID_CACHE_PREFIX = "rsc-id-";
-    private static final String RESOURCE_OWNER_CACHE_PREFIX = "rsc-owner-";
+    private static final String RESOURCE_NAME_CACHE_PREFIX = "rsc-name-";
 
     private final KeycloakSession session;
     private final CacheTransaction transaction;
+    private final List<String> cacheKeys;
     private StoreFactory storeFactory;
     private ResourceStore delegate;
-    private final Cache<String, List> cache;
+    private final Cache<String, List<CachedResource>> cache;
 
-    public CachedResourceStore(KeycloakSession session, CacheTransaction transaction) {
+    public CachedResourceStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
         InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
         this.cache = provider.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
         this.transaction = transaction;
+        cacheKeys = new ArrayList<>();
+        cacheKeys.add("findByOwner");
+        this.storeFactory = storeFactory;
     }
 
     @Override
     public Resource create(String name, ResourceServer resourceServer, String owner) {
         Resource resource = getDelegate().create(name, getStoreFactory().getResourceServerStore().findById(resourceServer.getId()), owner);
 
-        this.transaction.whenRollback(() -> cache.remove(getCacheKeyForResource(resource.getId())));
+        this.transaction.whenRollback(() -> {
+            cache.remove(getCacheKeyForResource(resource.getId()));
+            invalidateCache(resourceServer.getId());
+        });
 
         return createAdapter(new CachedResource(resource));
     }
 
     @Override
     public void delete(String id) {
-        List<CachedResource> removed = this.cache.remove(getCacheKeyForResource(id));
-
-        if (removed != null) {
-            CachedResource cachedResource = removed.get(0);
-            List<String> byOwner = this.cache.get(getResourceOwnerCacheKey(cachedResource.getOwner()));
-
-            if (byOwner != null) {
-                byOwner.remove(id);
+        Resource resource = findById(id, null);
+        ResourceServer resourceServer = resource.getResourceServer();
+        getDelegate().delete(id);
+        this.transaction.whenCommit(() -> {
+            List<CachedResource> resources = cache.remove(getCacheKeyForResource(id));
 
-                if (byOwner.isEmpty()) {
-                    this.cache.remove(getResourceOwnerCacheKey(cachedResource.getOwner()));
-                }
+            if (resources != null) {
+                CachedResource entry = resources.get(0);
+                cache.remove(getCacheKeyForResourceName(entry.getName(), entry.getResourceServerId()));
             }
-        }
 
-        getDelegate().delete(id);
+            invalidateCache(resourceServer.getId());
+        });
     }
 
     @Override
-    public Resource findById(String id) {
+    public Resource findById(String id, String resourceServerId) {
         String cacheKeyForResource = getCacheKeyForResource(id);
         List<CachedResource> cached = this.cache.get(cacheKeyForResource);
 
         if (cached == null) {
-            Resource resource = getDelegate().findById(id);
+            Resource resource = getDelegate().findById(id, resourceServerId);
 
             if (resource != null) {
-                updateCachedIds(getResourceOwnerCacheKey(resource.getOwner()), resource, false);
                 return createAdapter(updateResourceCache(resource));
             }
 
@@ -107,20 +113,13 @@ public class CachedResourceStore implements ResourceStore {
     }
 
     @Override
-    public List<Resource> findByOwner(String ownerId) {
-
-        for (Resource resource : getDelegate().findByOwner(ownerId)) {
-            updateCachedIds(getResourceOwnerCacheKey(ownerId), resource, true);
-        }
-
-        return  ((List<String>) this.cache.getOrDefault(getResourceOwnerCacheKey(ownerId), Collections.emptyList())).stream().map(this::findById)
-                        .filter(resource -> resource != null)
-                        .collect(Collectors.toList());
+    public List<Resource> findByOwner(String ownerId, String resourceServerId) {
+        return cacheResult(new StringBuilder("findByOwner").append(resourceServerId).append(ownerId).toString(), () -> getDelegate().findByOwner(ownerId, resourceServerId));
     }
 
     @Override
     public List<Resource> findByResourceServer(String resourceServerId) {
-        return getDelegate().findByResourceServer(resourceServerId).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
+        return getDelegate().findByResourceServer(resourceServerId);
     }
 
     @Override
@@ -129,43 +128,42 @@ public class CachedResourceStore implements ResourceStore {
     }
 
     @Override
-    public List<Resource> findByScope(String... id) {
-        return getDelegate().findByScope(id).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
+    public List<Resource> findByScope(List<String> id, String resourceServerId) {
+        return getDelegate().findByScope(id, resourceServerId);
     }
 
     @Override
     public Resource findByName(String name, String resourceServerId) {
-        for (Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
+        String cacheKeyForResource = getCacheKeyForResourceName(name, resourceServerId);
+        List<CachedResource> cached = this.cache.get(cacheKeyForResource);
 
-            if (cacheKey.startsWith(RESOURCE_ID_CACHE_PREFIX)) {
-                List<CachedResource> value = (List<CachedResource>) entry.getValue();
-                CachedResource resource = value.get(0);
+        if (cached == null) {
+            Resource resource = getDelegate().findByName(name, resourceServerId);
 
-                if (resource.getResourceServerId().equals(resourceServerId) && resource.getName().equals(name)) {
-                    return findById(resource.getId());
-                }
+            if (resource != null) {
+                cache.put(cacheKeyForResource, Arrays.asList(new CachedResource(resource)));
+                return findById(resource.getId(), resourceServerId);
             }
-        }
-
-        Resource resource = getDelegate().findByName(name, resourceServerId);
 
-        if (resource != null) {
-            return findById(updateResourceCache(resource).getId());
+            return null;
         }
 
-        return null;
+        return createAdapter(cached.get(0));
     }
 
     @Override
-    public List<Resource> findByType(String type) {
-        return  getDelegate().findByType(type).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
+    public List<Resource> findByType(String type, String resourceServerId) {
+        return  getDelegate().findByType(type, resourceServerId);
     }
 
     private String getCacheKeyForResource(String id) {
         return RESOURCE_ID_CACHE_PREFIX + id;
     }
 
+    private String getCacheKeyForResourceName(String name, String resourceServerId) {
+        return RESOURCE_NAME_CACHE_PREFIX + name + "-" + resourceServerId;
+    }
+
     private ResourceStore getDelegate() {
         if (this.delegate == null) {
             this.delegate = getStoreFactory().getResourceStore();
@@ -175,10 +173,6 @@ public class CachedResourceStore implements ResourceStore {
     }
 
     private StoreFactory getStoreFactory() {
-        if (this.storeFactory == null) {
-            this.storeFactory = session.getProvider(StoreFactory.class);
-        }
-
         return this.storeFactory;
     }
 
@@ -228,13 +222,15 @@ public class CachedResourceStore implements ResourceStore {
 
             @Override
             public List<Scope> getScopes() {
-                List<Scope> scopes = new ArrayList<>();
+                if (scopes == null) {
+                    scopes = new ArrayList<>();
 
-                for (String id : cached.getScopesIds()) {
-                    Scope cached = getStoreFactory().getScopeStore().findById(id);
+                    for (String id : cached.getScopesIds()) {
+                        Scope scope = getCachedStoreFactory().getScopeStore().findById(id, cached.getResourceServerId());
 
-                    if (cached != null) {
-                        scopes.add(cached);
+                        if (scope != null) {
+                            scopes.add(scope);
+                        }
                     }
                 }
 
@@ -254,7 +250,7 @@ public class CachedResourceStore implements ResourceStore {
 
             @Override
             public ResourceServer getResourceServer() {
-                return getStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
+                return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
             }
 
             @Override
@@ -264,15 +260,19 @@ public class CachedResourceStore implements ResourceStore {
 
             @Override
             public void updateScopes(Set<Scope> scopes) {
-                getDelegateForUpdate().updateScopes(scopes.stream().map(scope -> getStoreFactory().getScopeStore().findById(scope.getId())).collect(Collectors.toSet()));
+                getDelegateForUpdate().updateScopes(scopes.stream().map(scope -> getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId())).collect(Collectors.toSet()));
                 cached.updateScopes(scopes);
             }
 
             private Resource getDelegateForUpdate() {
                 if (this.updated == null) {
-                    this.updated = getDelegate().findById(getId());
+                    this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
-                    transaction.whenCommit(() -> cache.remove(getCacheKeyForResource(getId())));
+                    transaction.whenRollback(() -> {
+                        cache.remove(getCacheKeyForResource(cached.getId()));
+                        invalidateCache(cached.getResourceServerId());
+                        getCachedStoreFactory().getPolicyStore().notifyChange(cached);
+                    });
                 }
 
                 return this.updated;
@@ -280,6 +280,10 @@ public class CachedResourceStore implements ResourceStore {
         };
     }
 
+    private CachedStoreFactoryProvider getCachedStoreFactory() {
+        return session.getProvider(CachedStoreFactoryProvider.class);
+    }
+
     private CachedResource updateResourceCache(Resource resource) {
         CachedResource cached = new CachedResource(resource);
         List cache = new ArrayList<>();
@@ -291,23 +295,25 @@ public class CachedResourceStore implements ResourceStore {
         return cached;
     }
 
-    private void updateCachedIds(String cacheKey, Resource resource, boolean create) {
-        List<String> cached = this.cache.get(cacheKey);
+    private List<Resource> cacheResult(String key, Supplier<List<Resource>> provider) {
+        List<CachedResource> cached = cache.computeIfAbsent(key, (Function<String, List<CachedResource>>) o -> {
+            List<Resource> result = provider.get();
 
-        if (cached == null) {
-            if (!create) {
-                return;
+            if (result.isEmpty()) {
+                return null;
             }
-            cached = new ArrayList<>();
-            this.cache.put(cacheKey, cached);
-        }
 
-        if (cached != null && !cached.contains(resource.getId())) {
-            cached.add(resource.getId());
+            return result.stream().map(resource -> new CachedResource(resource)).collect(Collectors.toList());
+        });
+
+        if (cached == null) {
+            return Collections.emptyList();
         }
+
+        return cached.stream().map(this::createAdapter).collect(Collectors.toList());
     }
 
-    private String getResourceOwnerCacheKey(String ownerId) {
-        return RESOURCE_OWNER_CACHE_PREFIX + ownerId;
+    private void invalidateCache(String resourceServerId) {
+        cacheKeys.forEach(cacheKey -> cache.keySet().stream().filter(key -> key.startsWith(cacheKey + resourceServerId)).forEach(cache::remove));
     }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
index f86a7d1..77a6970 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
@@ -18,6 +18,11 @@
 
 package org.keycloak.models.authorization.infinispan;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
 import org.infinispan.Cache;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
@@ -27,11 +32,7 @@ import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.authorization.infinispan.InfinispanStoreFactoryProvider.CacheTransaction;
 import org.keycloak.models.authorization.infinispan.entities.CachedScope;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -39,6 +40,7 @@ import java.util.Map.Entry;
 public class CachedScopeStore implements ScopeStore {
 
     private static final String SCOPE_ID_CACHE_PREFIX = "scp-id-";
+    private static final String SCOPE_NAME_CACHE_PREFIX = "scp-name-";
 
     private final Cache<String, List> cache;
     private final KeycloakSession session;
@@ -46,11 +48,12 @@ public class CachedScopeStore implements ScopeStore {
     private ScopeStore delegate;
     private StoreFactory storeFactory;
 
-    public CachedScopeStore(KeycloakSession session, CacheTransaction transaction) {
+    public CachedScopeStore(KeycloakSession session, CacheTransaction transaction, StoreFactory storeFactory) {
         this.session = session;
         this.transaction = transaction;
         InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
         this.cache = provider.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME);
+        this.storeFactory = storeFactory;
     }
 
     @Override
@@ -65,16 +68,23 @@ public class CachedScopeStore implements ScopeStore {
     @Override
     public void delete(String id) {
         getDelegate().delete(id);
-        this.transaction.whenCommit(() -> cache.remove(getCacheKeyForScope(id)));
+        this.transaction.whenCommit(() -> {
+            List<CachedScope> scopes = cache.remove(getCacheKeyForScope(id));
+
+            if (scopes != null) {
+                CachedScope entry = scopes.get(0);
+                cache.remove(getCacheKeyForScopeName(entry.getName(), entry.getResourceServerId()));
+            }
+        });
     }
 
     @Override
-    public Scope findById(String id) {
+    public Scope findById(String id, String resourceServerId) {
         String cacheKeyForScope = getCacheKeyForScope(id);
         List<CachedScope> cached = this.cache.get(cacheKeyForScope);
 
         if (cached == null) {
-            Scope scope = getDelegate().findById(id);
+            Scope scope = getDelegate().findById(id, resourceServerId);
 
             if (scope != null) {
                 return createAdapter(updateScopeCache(scope));
@@ -88,26 +98,21 @@ public class CachedScopeStore implements ScopeStore {
 
     @Override
     public Scope findByName(String name, String resourceServerId) {
-        for (Entry entry : this.cache.entrySet()) {
-            String cacheKey = (String) entry.getKey();
+        String cacheKeyForScope = getCacheKeyForScopeName(name, resourceServerId);
+        List<String> cached = this.cache.get(cacheKeyForScope);
 
-            if (cacheKey.startsWith(SCOPE_ID_CACHE_PREFIX)) {
-                List<CachedScope> cache = (List<CachedScope>) entry.getValue();
-                CachedScope scope = cache.get(0);
+        if (cached == null) {
+            Scope scope = getDelegate().findByName(name, resourceServerId);
 
-                if (scope.getResourceServerId().equals(resourceServerId) && scope.getName().equals(name)) {
-                    return findById(scope.getId());
-                }
+            if (scope != null) {
+                cache.put(cacheKeyForScope, Arrays.asList(scope.getId()));
+                return findById(scope.getId(), resourceServerId);
             }
-        }
 
-        Scope scope = getDelegate().findByName(name, resourceServerId);
-
-        if (scope != null) {
-            return findById(updateScopeCache(scope).getId());
+            return null;
         }
 
-        return null;
+        return findById(cached.get(0), resourceServerId);
     }
 
     @Override
@@ -124,6 +129,10 @@ public class CachedScopeStore implements ScopeStore {
         return SCOPE_ID_CACHE_PREFIX + id;
     }
 
+    private String getCacheKeyForScopeName(String name, String resourceServerId) {
+        return SCOPE_NAME_CACHE_PREFIX + name + "-" + resourceServerId;
+    }
+
     private ScopeStore getDelegate() {
         if (this.delegate == null) {
             this.delegate = getStoreFactory().getScopeStore();
@@ -133,10 +142,6 @@ public class CachedScopeStore implements ScopeStore {
     }
 
     private StoreFactory getStoreFactory() {
-        if (this.storeFactory == null) {
-            this.storeFactory = session.getProvider(StoreFactory.class);
-        }
-
         return this.storeFactory;
     }
 
@@ -174,14 +179,17 @@ public class CachedScopeStore implements ScopeStore {
 
             @Override
             public ResourceServer getResourceServer() {
-                return getStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
+                return getCachedStoreFactory().getResourceServerStore().findById(cached.getResourceServerId());
             }
 
             private Scope getDelegateForUpdate() {
                 if (this.updated == null) {
-                    this.updated = getDelegate().findById(getId());
+                    this.updated = getDelegate().findById(getId(), cached.getResourceServerId());
                     if (this.updated == null) throw new IllegalStateException("Not found in database");
-                    transaction.whenCommit(() -> cache.remove(getCacheKeyForScope(getId())));
+                    transaction.whenCommit(() -> {
+                        cache.remove(getCacheKeyForScope(getId()));
+                        getCachedStoreFactory().getPolicyStore().notifyChange(updated);
+                    });
                 }
 
                 return this.updated;
@@ -189,6 +197,10 @@ public class CachedScopeStore implements ScopeStore {
         };
     }
 
+    private CachedStoreFactoryProvider getCachedStoreFactory() {
+        return session.getProvider(CachedStoreFactoryProvider.class);
+    }
+
     private CachedScope updateScopeCache(Scope scope) {
         CachedScope cached = new CachedScope(scope);
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
index 56a385f..ff66da6 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
@@ -22,6 +22,7 @@ import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceServerStore;
 import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.authorization.store.ScopeStore;
+import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakTransaction;
 import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
@@ -36,31 +37,41 @@ public class InfinispanStoreFactoryProvider implements CachedStoreFactoryProvide
 
     private final KeycloakSession session;
     private final CacheTransaction transaction;
+    private final StoreFactory storeFactory;
+    private final CachedResourceStore resourceStore;
+    private final CachedScopeStore scopeStore;
+    private final CachedPolicyStore policyStore;
+    private ResourceServerStore resourceServerStore;
 
     InfinispanStoreFactoryProvider(KeycloakSession delegate) {
         this.session = delegate;
         this.transaction = new CacheTransaction();
         this.session.getTransactionManager().enlistAfterCompletion(transaction);
+        storeFactory = this.session.getProvider(StoreFactory.class);
+        resourceStore = new CachedResourceStore(this.session, this.transaction, storeFactory);
+        resourceServerStore = new CachedResourceServerStore(this.session, this.transaction, storeFactory);
+        scopeStore = new CachedScopeStore(this.session, this.transaction, storeFactory);
+        policyStore = new CachedPolicyStore(this.session, this.transaction, storeFactory);
     }
 
     @Override
     public ResourceStore getResourceStore() {
-        return new CachedResourceStore(this.session, this.transaction);
+        return resourceStore;
     }
 
     @Override
     public ResourceServerStore getResourceServerStore() {
-        return new CachedResourceServerStore(this.session, this.transaction);
+        return resourceServerStore;
     }
 
     @Override
     public ScopeStore getScopeStore() {
-        return new CachedScopeStore(this.session, this.transaction);
+        return scopeStore;
     }
 
     @Override
     public PolicyStore getPolicyStore() {
-        return new CachedPolicyStore(this.session, this.transaction);
+        return policyStore;
     }
 
     @Override
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
index e1ba326..648b1b3 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/PolicyEntity.java
@@ -18,11 +18,10 @@
 
 package org.keycloak.authorization.jpa.entities;
 
-import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.model.Resource;
-import org.keycloak.authorization.model.Scope;
-import org.keycloak.representations.idm.authorization.DecisionStrategy;
-import org.keycloak.representations.idm.authorization.Logic;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 import javax.persistence.Access;
 import javax.persistence.AccessType;
@@ -34,15 +33,17 @@ import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.MapKeyColumn;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.UniqueConstraint;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.Logic;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -79,19 +80,19 @@ public class PolicyEntity implements Policy {
     @CollectionTable(name="POLICY_CONFIG", joinColumns={ @JoinColumn(name="POLICY_ID") })
     private Map<String, String> config = new HashMap();
 
-    @ManyToOne(optional = false)
+    @ManyToOne(optional = false, fetch = FetchType.LAZY)
     @JoinColumn(name = "RESOURCE_SERVER_ID")
     private ResourceServerEntity resourceServer;
 
-    @ManyToMany(fetch = FetchType.LAZY, cascade = {})
+    @OneToMany(fetch = FetchType.LAZY, cascade = {})
     @JoinTable(name = "ASSOCIATED_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "ASSOCIATED_POLICY_ID"))
     private Set<PolicyEntity> associatedPolicies = new HashSet<>();
 
-    @ManyToMany(fetch = FetchType.LAZY, cascade = {})
+    @OneToMany(fetch = FetchType.LAZY, cascade = {})
     @JoinTable(name = "RESOURCE_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "RESOURCE_ID"))
     private Set<ResourceEntity> resources = new HashSet<>();
 
-    @ManyToMany(fetch = FetchType.EAGER, cascade = {})
+    @OneToMany(fetch = FetchType.EAGER, cascade = {})
     @JoinTable(name = "SCOPE_POLICY", joinColumns = @JoinColumn(name = "POLICY_ID"), inverseJoinColumns = @JoinColumn(name = "SCOPE_ID"))
     private Set<ScopeEntity> scopes = new HashSet<>();
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java
index 7cb1a6f..29b5740 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ResourceEntity.java
@@ -67,7 +67,7 @@ public class ResourceEntity implements Resource {
     @Column(name = "OWNER")
     private String owner;
 
-    @ManyToOne(optional = false)
+    @ManyToOne(optional = false, fetch = FetchType.LAZY)
     @JoinColumn(name = "RESOURCE_SERVER_ID")
     private ResourceServerEntity resourceServer;
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ScopeEntity.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ScopeEntity.java
index 99f8b41..9f2c3b8 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ScopeEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/entities/ScopeEntity.java
@@ -57,7 +57,7 @@ public class ScopeEntity implements Scope {
     @Column(name = "ICON_URI")
     private String iconUri;
 
-    @ManyToOne(optional = false)
+    @ManyToOne(optional = false, fetch = FetchType.LAZY)
     @JoinColumn(name = "RESOURCE_SERVER_ID")
     private ResourceServerEntity resourceServer;
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
index b57cd1e..544018d 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
@@ -19,8 +19,10 @@ package org.keycloak.authorization.jpa.store;
 
 import org.keycloak.authorization.jpa.entities.PolicyEntity;
 import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
+import org.keycloak.authorization.jpa.entities.ScopeEntity;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
@@ -68,17 +70,30 @@ public class JPAPolicyStore implements PolicyStore {
 
     @Override
     public void delete(String id) {
-        Policy policy = findById(id);
+        Policy policy = entityManager.find(PolicyEntity.class, id);
 
         if (policy != null) {
-            getEntityManager().remove(policy);
+            this.entityManager.remove(policy);
         }
     }
 
 
     @Override
-    public Policy findById(String id) {
-        return getEntityManager().find(PolicyEntity.class, id);
+    public Policy findById(String id, String resourceServerId) {
+        if (id == null) {
+            return null;
+        }
+
+        if (resourceServerId == null) {
+            return entityManager.find(PolicyEntity.class, id);
+        }
+
+        Query query = entityManager.createQuery("from PolicyEntity where resourceServer.id = :serverId and id = :id");
+
+        query.setParameter("serverId", resourceServerId);
+        query.setParameter("id", id);
+
+        return entityManager.find(PolicyEntity.class, id);
     }
 
     @Override
@@ -142,32 +157,23 @@ public class JPAPolicyStore implements PolicyStore {
     }
 
     @Override
-    public List<Policy> findByResource(final String resourceId) {
-        Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.resources r where r.id = :resourceId");
+    public List<Policy> findByResource(final String resourceId, String resourceServerId) {
+        Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.resources r where p.resourceServer.id = :serverId and (r.resourceServer.id = :serverId and r.id = :resourceId)");
 
         query.setParameter("resourceId", resourceId);
+        query.setParameter("serverId", resourceServerId);
 
         return query.getResultList();
     }
 
     @Override
     public List<Policy> findByResourceType(final String resourceType, String resourceServerId) {
-        List<Policy> policies = new ArrayList<>();
-        Query query = getEntityManager().createQuery("from PolicyEntity where resourceServer.id = :serverId");
+        Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.config c where p.resourceServer.id = :serverId and KEY(c) = 'defaultResourceType' and c = :type");
 
         query.setParameter("serverId", resourceServerId);
+        query.setParameter("type", resourceType);
 
-        List<Policy> models = query.getResultList();
-
-        for (Policy policy : models) {
-            String defaultType = policy.getConfig().get("defaultResourceType");
-
-            if (defaultType != null && defaultType.equals(resourceType) && policy.getResources().isEmpty()) {
-                policies.add(policy);
-            }
-        }
-
-        return policies;
+        return query.getResultList();
     }
 
     @Override
@@ -177,7 +183,7 @@ public class JPAPolicyStore implements PolicyStore {
         }
 
         // Use separate subquery to handle DB2 and MSSSQL
-        Query query = getEntityManager().createQuery("select pe from PolicyEntity pe where pe.id IN (select p.id from PolicyEntity p inner join p.scopes s where p.resourceServer.id = :serverId and s.id in (:scopeIds) and p.resources is empty group by p.id) order by pe.name");
+        Query query = getEntityManager().createQuery("select pe from PolicyEntity pe where pe.resourceServer.id = :serverId and pe.id IN (select p.id from ScopeEntity s inner join s.policies p where s.resourceServer.id = :serverId and (p.resourceServer.id = :serverId and p.type = 'scope' and s.id in (:scopeIds)))");
 
         query.setParameter("serverId", resourceServerId);
         query.setParameter("scopeIds", scopeIds);
@@ -186,19 +192,21 @@ public class JPAPolicyStore implements PolicyStore {
     }
 
     @Override
-    public List<Policy> findByType(String type) {
-        Query query = getEntityManager().createQuery("select p from PolicyEntity p where p.type = :type");
+    public List<Policy> findByType(String type, String resourceServerId) {
+        Query query = getEntityManager().createQuery("select p from PolicyEntity p where p.resourceServer.id = :serverId and p.type = :type");
 
+        query.setParameter("serverId", resourceServerId);
         query.setParameter("type", type);
 
         return query.getResultList();
     }
 
     @Override
-    public List<Policy> findDependentPolicies(String policyId) {
-        Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.associatedPolicies ap where ap.id in (:policyId)");
+    public List<Policy> findDependentPolicies(String policyId, String resourceServerId) {
+        Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.associatedPolicies ap where p.resourceServer.id = :serverId and (ap.resourceServer.id = :serverId and ap.id = :policyId)");
 
-        query.setParameter("policyId", Arrays.asList(policyId));
+        query.setParameter("serverId", resourceServerId);
+        query.setParameter("policyId", policyId);
 
         return query.getResultList();
     }
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
index 6d00bb6..9f5346d 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
@@ -66,7 +66,7 @@ public class JPAResourceStore implements ResourceStore {
 
     @Override
     public void delete(String id) {
-        Resource resource = findById(id);
+        Resource resource = entityManager.find(ResourceEntity.class, id);
 
         resource.getScopes().clear();
 
@@ -76,19 +76,29 @@ public class JPAResourceStore implements ResourceStore {
     }
 
     @Override
-    public Resource findById(String id) {
+    public Resource findById(String id, String resourceServerId) {
         if (id == null) {
             return null;
         }
 
+        if (resourceServerId == null) {
+            return entityManager.find(ResourceEntity.class, id);
+        }
+
+        Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and id = :id");
+
+        query.setParameter("serverId", resourceServerId);
+        query.setParameter("id", id);
+
         return entityManager.find(ResourceEntity.class, id);
     }
 
     @Override
-    public List<Resource> findByOwner(String ownerId) {
-        Query query = entityManager.createQuery("from ResourceEntity where owner = :ownerId");
+    public List<Resource> findByOwner(String ownerId, String resourceServerId) {
+        Query query = entityManager.createQuery("from ResourceEntity where resourceServer.id = :serverId and owner = :ownerId");
 
         query.setParameter("ownerId", ownerId);
+        query.setParameter("serverId", resourceServerId);
 
         return query.getResultList();
     }
@@ -112,7 +122,9 @@ public class JPAResourceStore implements ResourceStore {
         predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
 
         attributes.forEach((name, value) -> {
-            if ("scope".equals(name)) {
+            if ("id".equals(name)) {
+                predicates.add(root.get(name).in(value));
+            } else if ("scope".equals(name)) {
                 predicates.add(root.join("scopes").get("id").in(value));
             } else {
                 predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
@@ -134,10 +146,11 @@ public class JPAResourceStore implements ResourceStore {
     }
 
     @Override
-    public List<Resource> findByScope(String... id) {
-        Query query = entityManager.createQuery("select r from ResourceEntity r inner join r.scopes s where s.id in (:scopeIds)");
+    public List<Resource> findByScope(List<String> id, String resourceServerId) {
+        Query query = entityManager.createQuery("select r from ResourceEntity r inner join r.scopes s where r.resourceServer.id = :serverId and (s.resourceServer.id = :serverId and s.id in (:scopeIds))");
 
-        query.setParameter("scopeIds", Arrays.asList(id));
+        query.setParameter("scopeIds", id);
+        query.setParameter("serverId", resourceServerId);
 
         return query.getResultList();
     }
@@ -159,10 +172,11 @@ public class JPAResourceStore implements ResourceStore {
     }
 
     @Override
-    public List<Resource> findByType(String type) {
-        Query query = entityManager.createQuery("from ResourceEntity where type = :type");
+    public List<Resource> findByType(String type, String resourceServerId) {
+        Query query = entityManager.createQuery("from ResourceEntity r where r.resourceServer.id = :serverId and type = :type");
 
         query.setParameter("type", type);
+        query.setParameter("serverId", resourceServerId);
 
         return query.getResultList();
     }
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
index d468314..30869d3 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
@@ -17,12 +17,9 @@
  */
 package org.keycloak.authorization.jpa.store;
 
-import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
-import org.keycloak.authorization.jpa.entities.ScopeEntity;
-import org.keycloak.authorization.model.ResourceServer;
-import org.keycloak.authorization.model.Scope;
-import org.keycloak.authorization.store.ScopeStore;
-import org.keycloak.models.utils.KeycloakModelUtils;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
@@ -31,9 +28,13 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+
+import org.keycloak.authorization.jpa.entities.ResourceServerEntity;
+import org.keycloak.authorization.jpa.entities.ScopeEntity;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
+import org.keycloak.authorization.store.ScopeStore;
+import org.keycloak.models.utils.KeycloakModelUtils;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -61,12 +62,30 @@ public class JPAScopeStore implements ScopeStore {
 
     @Override
     public void delete(String id) {
-        this.entityManager.remove(findById(id));
+        Scope scope = entityManager.find(ScopeEntity.class, id);
+
+        if (scope != null) {
+            this.entityManager.remove(scope);
+        }
     }
 
     @Override
-    public Scope findById(String id) {
+    public Scope findById(String id, String resourceServerId) {
+        if (id == null) {
+            return null;
+        }
+
+        if (true) {
+            return entityManager.find(ScopeEntity.class, id);
+        }
+
+        Query query = entityManager.createQuery("from ScopeEntity where resourceServer.id = :serverId and id = :id");
+
+        query.setParameter("serverId", resourceServerId);
+        query.setParameter("id", id);
+
         return entityManager.find(ScopeEntity.class, id);
+
     }
 
     @Override
@@ -74,8 +93,8 @@ public class JPAScopeStore implements ScopeStore {
         try {
             Query query = entityManager.createQuery("select s from ScopeEntity s inner join s.resourceServer rs where rs.id = :resourceServerId and name = :name");
 
-            query.setParameter("name", name);
             query.setParameter("resourceServerId", resourceServerId);
+            query.setParameter("name", name);
 
             return (Scope) query.getSingleResult();
         } catch (NoResultException nre) {
@@ -102,7 +121,11 @@ public class JPAScopeStore implements ScopeStore {
         predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
 
         attributes.forEach((name, value) -> {
-            predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
+            if ("id".equals(name)) {
+                predicates.add(root.get(name).in(value));
+            } else {
+                predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
+            }
         });
 
         querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/PolicyAdapter.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/PolicyAdapter.java
index 2b28f16..928bba9 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/PolicyAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/PolicyAdapter.java
@@ -124,21 +124,21 @@ public class PolicyAdapter extends AbstractMongoAdapter<PolicyEntity> implements
     @Override
     public Set<Policy> getAssociatedPolicies() {
         return getMongoEntity().getAssociatedPolicies().stream()
-                .map((Function<String, Policy>) id -> authorizationProvider.getStoreFactory().getPolicyStore().findById(id))
+                .map((Function<String, Policy>) id -> authorizationProvider.getStoreFactory().getPolicyStore().findById(id, getMongoEntity().getResourceServerId()))
                 .collect(Collectors.toSet());
     }
 
     @Override
     public Set<Resource> getResources() {
         return getMongoEntity().getResources().stream()
-                .map((Function<String, Resource>) id -> authorizationProvider.getStoreFactory().getResourceStore().findById(id))
+                .map((Function<String, Resource>) id -> authorizationProvider.getStoreFactory().getResourceStore().findById(id, getMongoEntity().getResourceServerId()))
                 .collect(Collectors.toSet());
     }
 
     @Override
     public Set<Scope> getScopes() {
         return getMongoEntity().getScopes().stream()
-                .map((Function<String, Scope>) id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id))
+                .map((Function<String, Scope>) id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id, getMongoEntity().getResourceServerId()))
                 .collect(Collectors.toSet());
     }
 
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/ResourceAdapter.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/ResourceAdapter.java
index 7c67f6e..8138a24 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/ResourceAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/adapter/ResourceAdapter.java
@@ -68,7 +68,7 @@ public class ResourceAdapter extends AbstractMongoAdapter<ResourceEntity> implem
     @Override
     public List<Scope> getScopes() {
         return getMongoEntity().getScopes().stream()
-                .map(id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id))
+                .map(id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id, getResourceServer().getId()))
                 .collect(toList());
     }
 
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
index 04a3d9a..c7227f6 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
@@ -70,7 +70,7 @@ public class MongoPolicyStore implements PolicyStore {
     }
 
     @Override
-    public Policy findById(String id) {
+    public Policy findById(String id, String resourceServerId) {
         PolicyEntity entity = getMongoStore().loadEntity(PolicyEntity.class, id, getInvocationContext());
 
         if (entity == null) {
@@ -89,7 +89,7 @@ public class MongoPolicyStore implements PolicyStore {
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId())).findFirst().orElse(null);
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId)).findFirst().orElse(null);
     }
 
     @Override
@@ -99,7 +99,7 @@ public class MongoPolicyStore implements PolicyStore {
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
@@ -125,17 +125,18 @@ public class MongoPolicyStore implements PolicyStore {
         DBObject sort = new BasicDBObject("name", 1);
 
         return getMongoStore().loadEntities(PolicyEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
-                .map(policy -> findById(policy.getId())).collect(toList());
+                .map(policy -> findById(policy.getId(), resourceServerId)).collect(toList());
     }
 
     @Override
-    public List<Policy> findByResource(String resourceId) {
+    public List<Policy> findByResource(String resourceId, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("resources").is(resourceId)
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
@@ -150,7 +151,7 @@ public class MongoPolicyStore implements PolicyStore {
                     String defaultResourceType = policyEntity.getConfig().get("defaultResourceType");
                     return defaultResourceType != null && defaultResourceType.equals(resourceType);
                 })
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
@@ -162,29 +163,31 @@ public class MongoPolicyStore implements PolicyStore {
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
     @Override
-    public List<Policy> findByType(String type) {
+    public List<Policy> findByType(String type, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("type").is(type)
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
     @Override
-    public List<Policy> findDependentPolicies(String policyId) {
+    public List<Policy> findDependentPolicies(String policyId, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("associatedPolicies").is(policyId)
                 .get();
 
         return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
index a85de72..79f6a9e 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
@@ -70,7 +70,7 @@ public class MongoResourceStore implements ResourceStore {
     }
 
     @Override
-    public Resource findById(String id) {
+    public Resource findById(String id, String resourceServerId) {
         ResourceEntity entity = getMongoStore().loadEntity(ResourceEntity.class, id, getInvocationContext());
 
         if (entity == null) {
@@ -81,13 +81,14 @@ public class MongoResourceStore implements ResourceStore {
     }
 
     @Override
-    public List<Resource> findByOwner(String ownerId) {
+    public List<Resource> findByOwner(String ownerId, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("owner").is(ownerId)
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
-                .map(scope -> findById(scope.getId())).collect(toList());
+                .map(scope -> findById(scope.getId(), resourceServerId)).collect(toList());
     }
 
     @Override
@@ -97,7 +98,7 @@ public class MongoResourceStore implements ResourceStore {
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
-                .map(scope -> findById(scope.getId())).collect(toList());
+                .map(scope -> findById(scope.getId(), resourceServerId)).collect(toList());
     }
 
     @Override
@@ -116,39 +117,41 @@ public class MongoResourceStore implements ResourceStore {
         DBObject sort = new BasicDBObject("name", 1);
 
         return getMongoStore().loadEntities(ResourceEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
-                .map(scope -> findById(scope.getId())).collect(toList());
+                .map(scope -> findById(scope.getId(), resourceServerId)).collect(toList());
     }
 
     @Override
-    public List<Resource> findByScope(String... id) {
+    public List<Resource> findByScope(List<String> id, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("scopes").in(id)
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
     @Override
     public Resource findByName(String name, String resourceServerId) {
         DBObject query = new QueryBuilder()
-                .and("name").is(name)
                 .and("resourceServerId").is(resourceServerId)
+                .and("name").is(name)
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId())).findFirst().orElse(null);
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId)).findFirst().orElse(null);
     }
 
     @Override
-    public List<Resource> findByType(String type) {
+    public List<Resource> findByType(String type, String resourceServerId) {
         DBObject query = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId)
                 .and("type").is(type)
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(policyEntity -> findById(policyEntity.getId(), resourceServerId))
                 .collect(toList());
     }
 
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
index 4b7edd6..04decb2 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
@@ -69,7 +69,7 @@ public class MongoScopeStore implements ScopeStore {
     }
 
     @Override
-    public Scope findById(String id) {
+    public Scope findById(String id, String resourceServerId) {
         ScopeEntity entity = getMongoStore().loadEntity(ScopeEntity.class, id, getInvocationContext());
 
         if (entity == null) {
@@ -87,7 +87,7 @@ public class MongoScopeStore implements ScopeStore {
                 .get();
 
         return getMongoStore().loadEntities(ScopeEntity.class, query, getInvocationContext()).stream()
-                .map(scope -> findById(scope.getId())).findFirst().orElse(null);
+                .map(scope -> findById(scope.getId(), scope.getResourceServerId())).findFirst().orElse(null);
     }
 
     @Override
@@ -97,7 +97,7 @@ public class MongoScopeStore implements ScopeStore {
                 .get();
 
         return getMongoStore().loadEntities(ScopeEntity.class, query, getInvocationContext()).stream()
-                .map(policyEntity -> findById(policyEntity.getId()))
+                .map(scope -> findById(scope.getId(), scope.getResourceServerId()))
                 .collect(toList());
     }
 
@@ -113,7 +113,7 @@ public class MongoScopeStore implements ScopeStore {
         DBObject sort = new BasicDBObject("name", 1);
 
         return getMongoStore().loadEntities(ScopeEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
-                .map(scope -> findById(scope.getId())).collect(toList());
+                .map(scope -> findById(scope.getId(), scope.getResourceServerId())).collect(toList());
     }
 
     private MongoStoreInvocationContext getInvocationContext() {
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java b/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
index fb7c91b..3aafae3 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/AuthorizationProvider.java
@@ -18,6 +18,12 @@
 
 package org.keycloak.authorization;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
+
 import org.keycloak.authorization.permission.evaluator.Evaluators;
 import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
@@ -26,11 +32,6 @@ import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderFactory;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.stream.Collectors;
 
 /**
  * <p>The main contract here is the creation of {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator} instances.  Usually
@@ -62,22 +63,22 @@ public final class AuthorizationProvider implements Provider {
 
     private final DefaultPolicyEvaluator policyEvaluator;
     private final Executor scheduller;
-    private final StoreFactory storeFactory;
-    private final List<PolicyProviderFactory> policyProviderFactories;
+    private final Supplier<StoreFactory> storeFactory;
+    private final Map<String, PolicyProviderFactory> policyProviderFactories;
     private final KeycloakSession keycloakSession;
     private final RealmModel realm;
 
-    public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory, Executor scheduller) {
+    public AuthorizationProvider(KeycloakSession session, RealmModel realm, Supplier<StoreFactory> storeFactory, Map<String, PolicyProviderFactory> policyProviderFactories, Executor scheduller) {
         this.keycloakSession = session;
         this.realm = realm;
         this.storeFactory = storeFactory;
         this.scheduller = scheduller;
-        this.policyProviderFactories = configurePolicyProviderFactories(session);
-        this.policyEvaluator = new DefaultPolicyEvaluator(this, this.policyProviderFactories);
+        this.policyProviderFactories = policyProviderFactories;
+        this.policyEvaluator = new DefaultPolicyEvaluator(this);
     }
 
-    public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory) {
-        this(session, realm, storeFactory, Runnable::run);
+    public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory, Map<String, PolicyProviderFactory> policyProviderFactories) {
+        this(session, realm, () -> storeFactory, policyProviderFactories, Runnable::run);
     }
 
     /**
@@ -87,7 +88,7 @@ public final class AuthorizationProvider implements Provider {
      * @return a {@link Evaluators} instance
      */
     public Evaluators evaluators() {
-        return new Evaluators(this.policyProviderFactories, this.policyEvaluator, this.scheduller);
+        return new Evaluators(this.policyEvaluator, this.scheduller);
     }
 
     /**
@@ -96,7 +97,7 @@ public final class AuthorizationProvider implements Provider {
      * @return the {@link StoreFactory}
      */
     public StoreFactory getStoreFactory() {
-        return this.storeFactory;
+        return this.storeFactory.get();
     }
 
     /**
@@ -104,8 +105,8 @@ public final class AuthorizationProvider implements Provider {
      *
      * @return a {@link List} containing all registered {@link PolicyProviderFactory}
      */
-    public List<PolicyProviderFactory> getProviderFactories() {
-        return this.policyProviderFactories;
+    public Collection<PolicyProviderFactory> getProviderFactories() {
+        return this.policyProviderFactories.values();
     }
 
     /**
@@ -116,7 +117,24 @@ public final class AuthorizationProvider implements Provider {
      * @return a {@link PolicyProviderFactory} with the given <code>type</code>
      */
     public <F extends PolicyProviderFactory> F getProviderFactory(String type) {
-        return (F) getProviderFactories().stream().filter(policyProviderFactory -> policyProviderFactory.getId().equals(type)).findFirst().orElse(null);
+        return (F) policyProviderFactories.get(type);
+    }
+
+    /**
+     * Returns a {@link PolicyProviderFactory} given a <code>type</code>.
+     *
+     * @param type the type of the policy provider
+     * @param <F> the expected type of the provider
+     * @return a {@link PolicyProvider} with the given <code>type</code>
+     */
+    public <P extends PolicyProvider> P getProvider(String type) {
+        PolicyProviderFactory policyProviderFactory = policyProviderFactories.get(type);
+
+        if (policyProviderFactory == null) {
+            return null;
+        }
+
+        return (P) policyProviderFactory.create(this);
     }
 
     public KeycloakSession getKeycloakSession() {
@@ -127,16 +145,6 @@ public final class AuthorizationProvider implements Provider {
         return realm;
     }
 
-    private List<PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSession session) {
-        List<ProviderFactory> providerFactories = session.getKeycloakSessionFactory().getProviderFactories(PolicyProvider.class);
-
-        if (providerFactories.isEmpty()) {
-            throw new RuntimeException("Could not find any policy provider.");
-        }
-
-        return providerFactories.stream().map(providerFactory -> (PolicyProviderFactory) providerFactory).collect(Collectors.toList());
-    }
-
     @Override
     public void close() {
 
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/Evaluators.java b/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/Evaluators.java
index e26ad1c..ed1aa89 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/Evaluators.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/Evaluators.java
@@ -18,13 +18,12 @@
 
 package org.keycloak.authorization.permission.evaluator;
 
+import java.util.List;
+import java.util.concurrent.Executor;
+
 import org.keycloak.authorization.permission.ResourcePermission;
 import org.keycloak.authorization.policy.evaluation.DefaultPolicyEvaluator;
 import org.keycloak.authorization.policy.evaluation.EvaluationContext;
-import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
-
-import java.util.List;
-import java.util.concurrent.Executor;
 
 /**
  * A factory for the different {@link PermissionEvaluator} implementations.
@@ -33,12 +32,10 @@ import java.util.concurrent.Executor;
  */
 public final class Evaluators {
 
-    private final List<PolicyProviderFactory> policyProviderFactories;
     private final DefaultPolicyEvaluator policyEvaluator;
     private final Executor scheduler;
 
-    public Evaluators(List<PolicyProviderFactory> policyProviderFactories, DefaultPolicyEvaluator policyEvaluator, Executor scheduler) {
-        this.policyProviderFactories = policyProviderFactories;
+    public Evaluators(DefaultPolicyEvaluator policyEvaluator, Executor scheduler) {
         this.policyEvaluator = policyEvaluator;
         this.scheduler = scheduler;
     }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/ScheduledPermissionEvaluator.java b/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/ScheduledPermissionEvaluator.java
index 13e08e4..4630507 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/ScheduledPermissionEvaluator.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/permission/evaluator/ScheduledPermissionEvaluator.java
@@ -17,11 +17,10 @@
  */
 package org.keycloak.authorization.permission.evaluator;
 
-import org.keycloak.authorization.Decision;
-
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 
+import org.keycloak.authorization.Decision;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  * @see PermissionEvaluator
@@ -38,6 +37,6 @@ class ScheduledPermissionEvaluator implements PermissionEvaluator {
 
     @Override
     public void evaluate(Decision decision) {
-        CompletableFuture.runAsync(() -> publisher.evaluate(decision), scheduler);
+        publisher.evaluate(decision);
     }
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionResultCollector.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionResultCollector.java
index abd3f93..2866360 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionResultCollector.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DecisionResultCollector.java
@@ -37,8 +37,10 @@ public abstract class DecisionResultCollector implements Decision<DefaultEvaluat
 
     @Override
     public void onDecision(DefaultEvaluation evaluation) {
-        if (evaluation.getParentPolicy() != null) {
-            results.computeIfAbsent(evaluation.getPermission(), Result::new).policy(evaluation.getParentPolicy()).policy(evaluation.getPolicy()).setStatus(evaluation.getEffect());
+        Policy parentPolicy = evaluation.getParentPolicy();
+
+        if (parentPolicy != null) {
+            results.computeIfAbsent(evaluation.getPermission(), Result::new).policy(parentPolicy).policy(evaluation.getPolicy()).setStatus(evaluation.getEffect());
         } else {
             results.computeIfAbsent(evaluation.getPermission(), Result::new).setStatus(evaluation.getEffect());
         }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
index 0bd5b6c..74a2e07 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultEvaluation.java
@@ -18,6 +18,7 @@
 
 package org.keycloak.authorization.policy.evaluation;
 
+import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.Decision;
 import org.keycloak.authorization.Decision.Effect;
 import org.keycloak.authorization.model.Policy;
@@ -34,37 +35,29 @@ public class DefaultEvaluation implements Evaluation {
     private final Decision decision;
     private final Policy policy;
     private final Policy parentPolicy;
+    private final AuthorizationProvider authorizationProvider;
     private Effect effect;
 
-    public DefaultEvaluation(ResourcePermission permission, EvaluationContext executionContext, Policy parentPolicy, Policy policy, Decision decision) {
+    public DefaultEvaluation(ResourcePermission permission, EvaluationContext executionContext, Policy parentPolicy, Policy policy, Decision decision, AuthorizationProvider authorizationProvider) {
         this.permission = permission;
         this.executionContext = executionContext;
         this.parentPolicy = parentPolicy;
         this.policy = policy;
         this.decision = decision;
+        this.authorizationProvider = authorizationProvider;
     }
 
-    /**
-     * Returns the {@link ResourcePermission} to be evaluated.
-     *
-     * @return the permission to be evaluated
-     */
+    @Override
     public ResourcePermission getPermission() {
         return this.permission;
     }
 
-    /**
-     * Returns the {@link org.keycloak.authorization.permission.evaluator.PermissionEvaluator}. Which provides access to the whole evaluation runtime context.
-     *
-     * @return the evaluation context
-     */
+    @Override
     public EvaluationContext getContext() {
         return this.executionContext;
     }
 
-    /**
-     * Grants all the requested permissions to the caller.
-     */
+    @Override
     public void grant() {
         if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
             this.effect = Effect.DENY;
@@ -75,6 +68,7 @@ public class DefaultEvaluation implements Evaluation {
         this.decision.onDecision(this);
     }
 
+    @Override
     public void deny() {
         if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
             this.effect = Effect.PERMIT;
@@ -85,10 +79,16 @@ public class DefaultEvaluation implements Evaluation {
         this.decision.onDecision(this);
     }
 
+    @Override
     public Policy getPolicy() {
         return this.policy;
     }
 
+    @Override
+    public AuthorizationProvider getAuthorizationProvider() {
+        return authorizationProvider;
+    }
+
     public Policy getParentPolicy() {
         return this.parentPolicy;
     }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultPolicyEvaluator.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultPolicyEvaluator.java
index 207c89e..b74f845 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultPolicyEvaluator.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/DefaultPolicyEvaluator.java
@@ -18,6 +18,14 @@
 
 package org.keycloak.authorization.policy.evaluation;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.Decision;
 import org.keycloak.authorization.model.Policy;
@@ -26,105 +34,95 @@ import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.permission.ResourcePermission;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
-import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class DefaultPolicyEvaluator implements PolicyEvaluator {
 
     private final AuthorizationProvider authorization;
-    private Map<String, PolicyProviderFactory> policyProviders = new HashMap<>();
+    private final StoreFactory storeFactory;
+    private final PolicyStore policyStore;
 
-    public DefaultPolicyEvaluator(AuthorizationProvider authorization, List<PolicyProviderFactory> policyProviderFactories) {
+    public DefaultPolicyEvaluator(AuthorizationProvider authorization) {
         this.authorization = authorization;
-
-        for (PolicyProviderFactory providerFactory : policyProviderFactories) {
-            this.policyProviders.put(providerFactory.getId(), providerFactory);
-        }
+        storeFactory = this.authorization.getStoreFactory();
+        policyStore = storeFactory.getPolicyStore();
     }
 
     @Override
     public void evaluate(ResourcePermission permission, EvaluationContext executionContext, Decision decision) {
         ResourceServer resourceServer = permission.getResourceServer();
+        PolicyEnforcementMode enforcementMode = resourceServer.getPolicyEnforcementMode();
 
-        if (PolicyEnforcementMode.DISABLED.equals(resourceServer.getPolicyEnforcementMode())) {
+        if (PolicyEnforcementMode.DISABLED.equals(enforcementMode)) {
             createEvaluation(permission, executionContext, decision, null, null).grant();
             return;
         }
 
-        StoreFactory storeFactory = this.authorization.getStoreFactory();
-        PolicyStore policyStore = storeFactory.getPolicyStore();
-        AtomicInteger policiesCount = new AtomicInteger(0);
-        Consumer<Policy> consumer = createDecisionConsumer(permission, executionContext, decision, policiesCount);
+        AtomicBoolean verified = new AtomicBoolean(false);
+        Consumer<Policy> consumer = createDecisionConsumer(permission, executionContext, decision, verified);
         Resource resource = permission.getResource();
+        List<Scope> scopes = permission.getScopes();
 
         if (resource != null) {
-            List<? extends Policy> resourcePolicies = policyStore.findByResource(resource.getId());
-
-            if (!resourcePolicies.isEmpty()) {
-                resourcePolicies.forEach(consumer);
-            }
+            evaluatePolicies(() -> policyStore.findByResource(resource.getId(), resourceServer.getId()), consumer);
 
             if (resource.getType() != null) {
-                policyStore.findByResourceType(resource.getType(), resourceServer.getId()).forEach(consumer);
+                evaluatePolicies(() -> policyStore.findByResourceType(resource.getType(), resourceServer.getId()), consumer);
             }
 
-            if (permission.getScopes().isEmpty() && !resource.getScopes().isEmpty()) {
-                policyStore.findByScopeIds(resource.getScopes().stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()).forEach(consumer);
+            if (scopes.isEmpty() && !resource.getScopes().isEmpty()) {
+                scopes.removeAll(resource.getScopes());
+                evaluatePolicies(() -> policyStore.findByScopeIds(resource.getScopes().stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()), consumer);
             }
         }
 
-        if (!permission.getScopes().isEmpty()) {
-            policyStore.findByScopeIds(permission.getScopes().stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()).forEach(consumer);
+        if (!scopes.isEmpty()) {
+            evaluatePolicies(() -> policyStore.findByScopeIds(scopes.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer.getId()), consumer);
         }
 
-        if (PolicyEnforcementMode.PERMISSIVE.equals(resourceServer.getPolicyEnforcementMode()) && policiesCount.get() == 0) {
+        if (PolicyEnforcementMode.PERMISSIVE.equals(enforcementMode) && verified.get()) {
             createEvaluation(permission, executionContext, decision, null, null).grant();
         }
     }
 
-    private  Consumer<Policy> createDecisionConsumer(ResourcePermission permission, EvaluationContext executionContext, Decision decision, AtomicInteger policiesCount) {
-        return (parentPolicy) -> {
-            if (hasRequestedScopes(permission, parentPolicy)) {
-                for (Policy associatedPolicy : parentPolicy.getAssociatedPolicies()) {
-                    PolicyProviderFactory providerFactory = policyProviders.get(associatedPolicy.getType());
+    private void evaluatePolicies(Supplier<List<Policy>> supplier, Consumer<Policy> consumer) {
+        List<Policy> policies = supplier.get();
 
-                    if (providerFactory == null) {
-                        throw new RuntimeException("Could not find a policy provider for policy type [" + associatedPolicy.getType() + "].");
-                    }
+        if (!policies.isEmpty()) {
+            policies.forEach(consumer);
+        }
+    }
 
-                    PolicyProvider policyProvider = providerFactory.create(associatedPolicy, this.authorization);
+    private Consumer<Policy> createDecisionConsumer(ResourcePermission permission, EvaluationContext executionContext, Decision decision, AtomicBoolean verified) {
+        return (parentPolicy) -> {
+            if (!hasRequestedScopes(permission, parentPolicy)) {
+                return;
+            }
 
-                    if (policyProvider == null) {
-                        throw new RuntimeException("Unknown parentPolicy provider for type [" + associatedPolicy.getType() + "].");
-                    }
+            for (Policy associatedPolicy : parentPolicy.getAssociatedPolicies()) {
+                PolicyProvider policyProvider = authorization.getProvider(associatedPolicy.getType());
 
-                    DefaultEvaluation evaluation = createEvaluation(permission, executionContext, decision, parentPolicy, associatedPolicy);
+                if (policyProvider == null) {
+                    throw new RuntimeException("Unknown parentPolicy provider for type [" + associatedPolicy.getType() + "].");
+                }
 
-                    policyProvider.evaluate(evaluation);
-                    evaluation.denyIfNoEffect();
+                DefaultEvaluation evaluation = createEvaluation(permission, executionContext, decision, parentPolicy, associatedPolicy);
 
-                    policiesCount.incrementAndGet();
-                }
+                policyProvider.evaluate(evaluation);
+                evaluation.denyIfNoEffect();
             }
+
+            verified.compareAndSet(false, true);
         };
     }
 
     private DefaultEvaluation createEvaluation(ResourcePermission permission, EvaluationContext executionContext, Decision decision, Policy parentPolicy, Policy associatedPolicy) {
-        return new DefaultEvaluation(permission, executionContext, parentPolicy, associatedPolicy, decision);
+        return new DefaultEvaluation(permission, executionContext, parentPolicy, associatedPolicy, decision, authorization);
     }
 
     private boolean hasRequestedScopes(final ResourcePermission permission, final Policy policy) {
@@ -136,7 +134,7 @@ public class DefaultPolicyEvaluator implements PolicyEvaluator {
         Set<Resource> policyResources = policy.getResources();
 
         if (resourcePermission != null && !policyResources.isEmpty()) {
-            if (!policyResources.stream().filter(resource -> resource.getId().equals(resourcePermission.getId())).findFirst().isPresent()) {
+                if (!policyResources.stream().filter(resource -> resource.getId().equals(resourcePermission.getId())).findFirst().isPresent()) {
                 return false;
             }
         }
@@ -161,7 +159,7 @@ public class DefaultPolicyEvaluator implements PolicyEvaluator {
                 String type = resource.getType();
 
                 if (type != null) {
-                    List<Resource> resourcesByType = authorization.getStoreFactory().getResourceStore().findByType(type);
+                    List<Resource> resourcesByType = authorization.getStoreFactory().getResourceStore().findByType(type, resource.getResourceServer().getId());
 
                     for (Resource resourceType : resourcesByType) {
                         if (resourceType.getOwner().equals(resource.getResourceServer().getClientId())) {
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
index f5b0868..4ac0264 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/evaluation/Evaluation.java
@@ -18,6 +18,8 @@
 
 package org.keycloak.authorization.policy.evaluation;
 
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.permission.ResourcePermission;
 
 /**
@@ -43,6 +45,15 @@ public interface Evaluation {
     EvaluationContext getContext();
 
     /**
+     * Returns the {@link Policy}. being evaluated.
+     *
+     * @return the evaluation context
+     */
+    Policy getPolicy();
+
+    AuthorizationProvider getAuthorizationProvider();
+
+    /**
      * Grants the requested permission to the caller.
      */
     void grant();
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java
index f82bdb7..f7041b5 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java
@@ -32,7 +32,7 @@ public interface PolicyProviderFactory extends ProviderFactory<PolicyProvider> {
 
     String getGroup();
 
-    PolicyProvider create(Policy policy, AuthorizationProvider authorization);
+    PolicyProvider create(AuthorizationProvider authorization);
 
     PolicyProviderAdminService getAdminResource(ResourceServer resourceServer);
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/store/PolicyStore.java b/server-spi-private/src/main/java/org/keycloak/authorization/store/PolicyStore.java
index 51c7dd7..626e317 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/store/PolicyStore.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/store/PolicyStore.java
@@ -53,9 +53,10 @@ public interface PolicyStore {
      * Returns a {@link Policy} with the given <code>id</code>
      *
      * @param id the identifier of the policy
+     * @param resourceServerId the resource server id
      * @return a policy with the given identifier.
      */
-    Policy findById(String id);
+    Policy findById(String id, String resourceServerId);
 
     /**
      * Returns a {@link Policy} with the given <code>name</code>
@@ -87,9 +88,10 @@ public interface PolicyStore {
      * Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>resourceId</code>.
      *
      * @param resourceId the identifier of a resource
+     * @param resourceServerId the resource server id
      * @return a list of policies associated with the given resource
      */
-    List<Policy> findByResource(String resourceId);
+    List<Policy> findByResource(String resourceId, String resourceServerId);
 
     /**
      * Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>type</code>.
@@ -113,15 +115,26 @@ public interface PolicyStore {
      * Returns a list of {@link Policy} with the given <code>type</code>.
      *
      * @param type the type of the policy
+     * @param resourceServerId the resource server id
      * @return a list of policies with the given type
      */
-    List<Policy> findByType(String type);
+    List<Policy> findByType(String type, String resourceServerId);
 
     /**
      * Returns a list of {@link Policy} that depends on another policy with the given <code>id</code>.
      *
      * @param id the id of the policy to query its dependents
+     * @param resourceServerId the resource server id
      * @return a list of policies that depends on the a policy with the given identifier
      */
-    List<Policy> findDependentPolicies(String id);
+    List<Policy> findDependentPolicies(String id, String resourceServerId);
+
+    /**
+     * Notify this store about changes to data associated with policies. E.g.: resources and scopes..
+     *
+     * TODO: need a better strategy to handle cross-references between stores, specially in cases where the store is caching data. Use some event-based solution here.
+     *
+     * @param cached
+     */
+    default void notifyChange(Object cached) {}
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/store/ResourceStore.java b/server-spi-private/src/main/java/org/keycloak/authorization/store/ResourceStore.java
index f06be78..e897664 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/store/ResourceStore.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/store/ResourceStore.java
@@ -53,7 +53,7 @@ public interface ResourceStore {
      * @param id the identifier of an existing resource instance
      * @return the resource instance with the given identifier or null if no instance was found
      */
-    Resource findById(String id);
+    Resource findById(String id, String resourceServerId);
 
     /**
      * Finds all {@link Resource} instances with the given {@code ownerId}.
@@ -61,7 +61,7 @@ public interface ResourceStore {
      * @param ownerId the identifier of the owner
      * @return a list with all resource instances owned by the given owner
      */
-    List<Resource> findByOwner(String ownerId);
+    List<Resource> findByOwner(String ownerId, String resourceServerId);
 
     /**
      * Finds all {@link Resource} instances associated with a given resource server.
@@ -86,7 +86,7 @@ public interface ResourceStore {
      * @param id one or more scope identifiers
      * @return a list of resources associated with the given scope(s)
      */
-    List<Resource> findByScope(String... id);
+    List<Resource> findByScope(List<String> id, String resourceServerId);
 
     /**
      * Find a {@link Resource} by its name.
@@ -103,5 +103,5 @@ public interface ResourceStore {
      * @param type the type of the resource
      * @return a list of resources with the given type
      */
-    List<Resource> findByType(String type);
+    List<Resource> findByType(String type, String resourceServerId);
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/store/ScopeStore.java b/server-spi-private/src/main/java/org/keycloak/authorization/store/ScopeStore.java
index 81a7064..fa9e70d 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/store/ScopeStore.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/store/ScopeStore.java
@@ -53,17 +53,17 @@ public interface ScopeStore {
      * Returns a {@link Scope} with the given <code>id</code>
      *
      * @param id the identifier of the scope
-     *
+     * @param resourceServerId the resource server id
      * @return a scope with the given identifier.
      */
-    Scope findById(String id);
+    Scope findById(String id, String resourceServerId);
 
     /**
      * Returns a {@link Scope} with the given <code>name</code>
      *
      * @param name the name of the scope
      *
-     * @param resourceServerId
+     * @param resourceServerId the resource server id
      * @return a scope with the given name.
      */
     Scope findByName(String name, String resourceServerId);
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/RealmSynchronizer.java b/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/RealmSynchronizer.java
index 4f0ef32..ed24c53 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/RealmSynchronizer.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/RealmSynchronizer.java
@@ -36,7 +36,7 @@ public class RealmSynchronizer implements Synchronizer<RealmRemovedEvent> {
         StoreFactory storeFactory = authorizationProvider.getStoreFactory();
 
         event.getRealm().getClients().forEach(clientModel -> {
-            ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel.getClientId());
+            ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel.getId());
 
             if (resourceServer != null) {
                 String id = resourceServer.getId();
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/UserSynchronizer.java b/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/UserSynchronizer.java
index 01830ff..03a2cda 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/UserSynchronizer.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/store/syncronization/UserSynchronizer.java
@@ -17,11 +17,16 @@
 
 package org.keycloak.authorization.store.syncronization;
 
+import java.util.function.Consumer;
+
 import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.store.PolicyStore;
+import org.keycloak.authorization.store.ResourceServerStore;
 import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.UserRemovedEvent;
 import org.keycloak.provider.ProviderFactory;
@@ -39,17 +44,25 @@ public class UserSynchronizer implements Synchronizer<UserRemovedEvent> {
         UserModel userModel = event.getUser();
         ResourceStore resourceStore = storeFactory.getResourceStore();
         PolicyStore policyStore = storeFactory.getPolicyStore();
+        ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
+        RealmModel realm = event.getRealm();
+
+        realm.getClients().forEach(clientModel -> {
+            ResourceServer resourceServer = resourceServerStore.findByClient(clientModel.getId());
 
-        resourceStore.findByOwner(userModel.getId()).forEach(resource -> {
-            String resourceId = resource.getId();
-            policyStore.findByResource(resourceId).forEach(policy -> {
-                if (policy.getResources().size() == 1) {
-                    policyStore.delete(policy.getId());
-                } else {
-                    policy.removeResource(resource);
-                }
-            });
-            resourceStore.delete(resourceId);
+            if (resourceServer != null) {
+                resourceStore.findByOwner(userModel.getId(), resourceServer.getId()).forEach(resource -> {
+                    String resourceId = resource.getId();
+                    policyStore.findByResource(resourceId, resourceServer.getId()).forEach(policy -> {
+                        if (policy.getResources().size() == 1) {
+                            policyStore.delete(policy.getId());
+                        } else {
+                            policy.removeResource(resource);
+                        }
+                    });
+                    resourceStore.delete(resourceId);
+                });
+            }
         });
     }
 }
diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
index 995dafb..f8844f1 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
@@ -70,7 +70,7 @@ public class MigrateTo2_1_0 implements Migration {
             ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(clientModel.getId());
 
             if (resourceServer != null) {
-                policyStore.findByType("role").forEach(policy -> {
+                policyStore.findByType("role", resourceServer.getId()).forEach(policy -> {
                     Map<String, String> config = policy.getConfig();
                     String roles = config.get("roles");
                     List roleConfig;
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 0a323e0..0ca0400 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -17,14 +17,23 @@
 
 package org.keycloak.models.utils;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
-import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceStore;
-import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.common.util.Time;
 import org.keycloak.component.ComponentModel;
@@ -84,20 +93,6 @@ import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.storage.StorageId;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -772,34 +767,16 @@ public class ModelToRepresentation {
     }
 
     public static ScopeRepresentation toRepresentation(Scope model, AuthorizationProvider authorizationProvider) {
+        return toRepresentation(model, authorizationProvider, true);
+    }
+
+    public static ScopeRepresentation toRepresentation(Scope model, AuthorizationProvider authorizationProvider, boolean deep) {
         ScopeRepresentation scope = new ScopeRepresentation();
 
         scope.setId(model.getId());
         scope.setName(model.getName());
         scope.setIconUri(model.getIconUri());
 
-        StoreFactory storeFactory = authorizationProvider.getStoreFactory();
-
-        scope.setResources(new ArrayList<>());
-
-        storeFactory.getResourceStore().findByScope(model.getId()).forEach(resource -> scope.getResources().add(toRepresentation(resource, resource.getResourceServer(), authorizationProvider)));
-
-        PolicyStore policyStore = storeFactory.getPolicyStore();
-
-        scope.setPolicies(new ArrayList<>());
-
-        policyStore.findByScopeIds(Arrays.asList(model.getId()), model.getResourceServer().getId()).forEach(policyModel -> {
-            PolicyRepresentation policy = new PolicyRepresentation();
-
-            policy.setId(policyModel.getId());
-            policy.setName(policyModel.getName());
-            policy.setType(policyModel.getType());
-
-            if (!scope.getPolicies().contains(policy)) {
-                scope.getPolicies().add(policy);
-            }
-        });
-
         return scope;
     }
 
@@ -815,7 +792,7 @@ public class ModelToRepresentation {
         return server;
     }
 
-    public static PolicyRepresentation toRepresentation(Policy model, AuthorizationProvider authorization) {
+    public static PolicyRepresentation toRepresentation(Policy model) {
         PolicyRepresentation representation = new PolicyRepresentation();
 
         representation.setId(model.getId());
@@ -824,45 +801,16 @@ public class ModelToRepresentation {
         representation.setType(model.getType());
         representation.setDecisionStrategy(model.getDecisionStrategy());
         representation.setLogic(model.getLogic());
-        representation.setConfig(new HashMap<>(model.getConfig()));
-
-        List<Policy> policies = authorization.getStoreFactory().getPolicyStore().findDependentPolicies(model.getId());
-
-        representation.setDependentPolicies(policies.stream().map(policy -> {
-            PolicyRepresentation representation1 = new PolicyRepresentation();
-
-            representation1.setId(policy.getId());
-            representation1.setName(policy.getName());
-
-            return representation1;
-        }).collect(Collectors.toList()));
-
-        List<PolicyRepresentation> associatedPolicies = new ArrayList<>();
-
-        List<String> obj = model.getAssociatedPolicies().stream().map(policy -> {
-            PolicyRepresentation representation1 = new PolicyRepresentation();
-
-            representation1.setId(policy.getId());
-            representation1.setName(policy.getName());
-            representation1.setType(policy.getType());
-
-            associatedPolicies.add(representation1);
-
-            return policy.getId();
-        }).collect(Collectors.toList());
-
-        representation.setAssociatedPolicies(associatedPolicies);
-
-        try {
-            representation.getConfig().put("applyPolicies", JsonSerialization.writeValueAsString(obj));
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+        representation.setConfig(model.getConfig());
 
         return representation;
     }
 
     public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization) {
+        return toRepresentation(model, resourceServer, authorization, true);
+    }
+
+    public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization, Boolean deep) {
         ResourceRepresentation resource = new ResourceRepresentation();
 
         resource.setId(model.getId());
@@ -893,55 +841,36 @@ public class ModelToRepresentation {
 
         resource.setOwner(owner);
 
-        resource.setScopes(model.getScopes().stream().map(model1 -> {
-            ScopeRepresentation scope = new ScopeRepresentation();
-            scope.setId(model1.getId());
-            scope.setName(model1.getName());
-            String iconUri = model1.getIconUri();
-            if (iconUri != null) {
-                scope.setIconUri(iconUri);
-            }
-            return scope;
-        }).collect(Collectors.toSet()));
-
-        resource.setTypedScopes(new ArrayList<>());
-
-        if (resource.getType() != null) {
-            ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
-            for (Resource typed : resourceStore.findByType(resource.getType())) {
-                if (typed.getOwner().equals(resourceServer.getClientId()) && !typed.getId().equals(resource.getId())) {
-                    resource.setTypedScopes(typed.getScopes().stream().map(model1 -> {
-                        ScopeRepresentation scope = new ScopeRepresentation();
-                        scope.setId(model1.getId());
-                        scope.setName(model1.getName());
-                        String iconUri = model1.getIconUri();
-                        if (iconUri != null) {
-                            scope.setIconUri(iconUri);
-                        }
-                        return scope;
-                    }).filter(scopeRepresentation -> !resource.getScopes().contains(scopeRepresentation)).collect(Collectors.toList()));
+        if (deep) {
+            resource.setScopes(model.getScopes().stream().map(model1 -> {
+                ScopeRepresentation scope = new ScopeRepresentation();
+                scope.setId(model1.getId());
+                scope.setName(model1.getName());
+                String iconUri = model1.getIconUri();
+                if (iconUri != null) {
+                    scope.setIconUri(iconUri);
+                }
+                return scope;
+            }).collect(Collectors.toSet()));
+
+            resource.setTypedScopes(new ArrayList<>());
+
+            if (resource.getType() != null) {
+                ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
+                for (Resource typed : resourceStore.findByType(resource.getType(), resourceServer.getId())) {
+                    if (typed.getOwner().equals(resourceServer.getClientId()) && !typed.getId().equals(resource.getId())) {
+                        resource.setTypedScopes(typed.getScopes().stream().map(model1 -> {
+                            ScopeRepresentation scope = new ScopeRepresentation();
+                            scope.setId(model1.getId());
+                            scope.setName(model1.getName());
+                            String iconUri = model1.getIconUri();
+                            if (iconUri != null) {
+                                scope.setIconUri(iconUri);
+                            }
+                            return scope;
+                        }).filter(scopeRepresentation -> !resource.getScopes().contains(scopeRepresentation)).collect(Collectors.toList()));
+                    }
                 }
-            }
-        }
-
-        resource.setPolicies(new ArrayList<>());
-
-        Set<Policy> policies = new HashSet<>();
-        PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
-
-        policies.addAll(policyStore.findByResource(resource.getId()));
-        policies.addAll(policyStore.findByResourceType(resource.getType(), resourceServer.getId()));
-        policies.addAll(policyStore.findByScopeIds(resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toList()), resourceServer.getId()));
-
-        for (Policy policyModel : policies) {
-            PolicyRepresentation policy = new PolicyRepresentation();
-
-            policy.setId(policyModel.getId());
-            policy.setName(policyModel.getName());
-            policy.setType(policyModel.getType());
-
-            if (!resource.getPolicies().contains(policy)) {
-                resource.getPolicies().add(policy);
             }
         }
 
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 96ffe8c..0fa958c 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1898,7 +1898,7 @@ public class RepresentationToModel {
 
             if (roles != null && !roles.isEmpty()) {
                 try {
-                    List<Map> rolesMap = JsonSerialization.readValue(roles, List.class);
+                    List<Map> rolesMap = (List<Map>)JsonSerialization.readValue(roles, List.class);
                     config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleConfig -> {
                         String roleName = roleConfig.get("id").toString();
                         String clientId = null;
@@ -1950,7 +1950,7 @@ public class RepresentationToModel {
 
             if (users != null && !users.isEmpty()) {
                 try {
-                    List<String> usersMap = JsonSerialization.readValue(users, List.class);
+                    List<String> usersMap = (List<String>) JsonSerialization.readValue(users, List.class);
                     config.put("users", JsonSerialization.writeValueAsString(usersMap.stream().map(userId -> {
                         UserModel user = session.users().getUserByUsername(userId, realm);
 
@@ -1974,12 +1974,12 @@ public class RepresentationToModel {
             if (scopes != null && !scopes.isEmpty()) {
                 try {
                     ScopeStore scopeStore = storeFactory.getScopeStore();
-                    List<String> scopesMap = JsonSerialization.readValue(scopes, List.class);
+                    List<String> scopesMap = (List<String>) JsonSerialization.readValue(scopes, List.class);
                     config.put("scopes", JsonSerialization.writeValueAsString(scopesMap.stream().map(scopeName -> {
                         Scope newScope = scopeStore.findByName(scopeName, resourceServer.getId());
 
                         if (newScope == null) {
-                            newScope = scopeStore.findById(scopeName);
+                            newScope = scopeStore.findById(scopeName, resourceServer.getId());
                         }
 
                         if (newScope == null) {
@@ -1999,21 +1999,18 @@ public class RepresentationToModel {
                 ResourceStore resourceStore = storeFactory.getResourceStore();
                 try {
                     List<String> resources = JsonSerialization.readValue(policyResources, List.class);
-                    config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(new Function<String, String>() {
-                        @Override
-                        public String apply(String resourceName) {
-                            Resource resource = resourceStore.findByName(resourceName, resourceServer.getId());
+                    config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(resourceName -> {
+                        Resource resource = resourceStore.findByName(resourceName, resourceServer.getId());
 
-                            if (resource == null) {
-                                resource = resourceStore.findById(resourceName);
-                            }
-
-                            if (resource == null) {
-                                throw new RuntimeException("Resource with name [" + resourceName + "] not defined.");
-                            }
+                        if (resource == null) {
+                            resource = resourceStore.findById(resourceName, resourceServer.getId());
+                        }
 
-                            return resource.getId();
+                        if (resource == null) {
+                            throw new RuntimeException("Resource with name [" + resourceName + "] not defined.");
                         }
+
+                        return resource.getId();
                     }).collect(Collectors.toList())));
                 } catch (Exception e) {
                     throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
@@ -2025,12 +2022,12 @@ public class RepresentationToModel {
             if (applyPolicies != null && !applyPolicies.isEmpty()) {
                 PolicyStore policyStore = storeFactory.getPolicyStore();
                 try {
-                    List<String> policies = JsonSerialization.readValue(applyPolicies, List.class);
+                    List<String> policies = (List<String>) JsonSerialization.readValue(applyPolicies, List.class);
                     config.put("applyPolicies", JsonSerialization.writeValueAsString(policies.stream().map(policyName -> {
                         Policy policy = policyStore.findByName(policyName, resourceServer.getId());
 
                         if (policy == null) {
-                            policy = policyStore.findById(policyName);
+                            policy = policyStore.findById(policyName, resourceServer.getId());
                         }
 
                         if (policy == null) {
@@ -2062,7 +2059,7 @@ public class RepresentationToModel {
         Policy existing;
 
         if (policy.getId() != null) {
-            existing = policyStore.findById(policy.getId());
+            existing = policyStore.findById(policy.getId(), resourceServer.getId());
         } else {
             existing = policyStore.findByName(policy.getName(), resourceServer.getId());
         }
@@ -2119,7 +2116,14 @@ public class RepresentationToModel {
                     }
                 }
                 if (!hasScope) {
-                    policy.addScope(storeFactory.getScopeStore().findById(scopeId));
+                    ResourceServer resourceServer = policy.getResourceServer();
+                    Scope scope = storeFactory.getScopeStore().findById(scopeId, resourceServer.getId());
+
+                    if (scope == null) {
+                        storeFactory.getScopeStore().findByName(scopeId, resourceServer.getId());
+                    }
+
+                    policy.addScope(scope);
                 }
             }
 
@@ -2135,6 +2139,8 @@ public class RepresentationToModel {
                     policy.removeScope(scopeModel);
                 }
             }
+
+            policy.getConfig().remove("scopes");
         }
     }
 
@@ -2164,7 +2170,7 @@ public class RepresentationToModel {
 
 
                 if (!hasPolicy) {
-                    Policy associatedPolicy = policyStore.findById(policyId);
+                    Policy associatedPolicy = policyStore.findById(policyId, resourceServer.getId());
 
                     if (associatedPolicy == null) {
                         associatedPolicy = policyStore.findByName(policyId, resourceServer.getId());
@@ -2186,6 +2192,8 @@ public class RepresentationToModel {
                     policy.removeAssociatedPolicy(policyModel);;
                 }
             }
+
+            policy.getConfig().remove("applyPolicies");
         }
     }
 
@@ -2210,7 +2218,7 @@ public class RepresentationToModel {
                     }
                 }
                 if (!hasResource && !"".equals(resourceId)) {
-                    policy.addResource(storeFactory.getResourceStore().findById(resourceId));
+                    policy.addResource(storeFactory.getResourceStore().findById(resourceId, policy.getResourceServer().getId()));
                 }
             }
 
@@ -2227,6 +2235,8 @@ public class RepresentationToModel {
                     policy.removeResource(resourceModel);
                 }
             }
+
+            policy.getConfig().remove("resources");
         }
     }
 
@@ -2235,7 +2245,7 @@ public class RepresentationToModel {
         Resource existing;
 
         if (resource.getId() != null) {
-            existing = resourceStore.findById(resource.getId());
+            existing = resourceStore.findById(resource.getId(), resourceServer.getId());
         } else {
             existing = resourceStore.findByName(resource.getName(), resourceServer.getId());
         }
@@ -2286,7 +2296,7 @@ public class RepresentationToModel {
         Scope existing;
 
         if (scope.getId() != null) {
-            existing = scopeStore.findById(scope.getId());
+            existing = scopeStore.findById(scope.getId(), resourceServer.getId());
         } else {
             existing = scopeStore.findByName(scope.getName(), resourceServer.getId());
         }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
index 076f9af..b096d24 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
@@ -17,6 +17,27 @@
  */
 package org.keycloak.authorization.admin;
 
+import static java.util.Arrays.asList;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.admin.representation.PolicyEvaluationRequest;
@@ -46,29 +67,10 @@ import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.services.Urls;
 import org.keycloak.services.resources.admin.RealmAuth;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Produces;
-import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.container.Suspended;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.Arrays.asList;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -144,40 +146,35 @@ public class PolicyEvaluationService {
     private List<ResourcePermission> createPermissions(PolicyEvaluationRequest representation, EvaluationContext evaluationContext, AuthorizationProvider authorization) {
         List<PolicyEvaluationRequest.Resource> resources = representation.getResources();
         return resources.stream().flatMap((Function<PolicyEvaluationRequest.Resource, Stream<ResourcePermission>>) resource -> {
-            Set<String> givenScopes = resource.getScopes();
+            StoreFactory storeFactory = authorization.getStoreFactory();
+            if (resource == null) {
+                resource = new PolicyEvaluationRequest.Resource();
+            }
+
+            Set<ScopeRepresentation> givenScopes = resource.getScopes();
 
             if (givenScopes == null) {
                 givenScopes = new HashSet();
             }
 
-            StoreFactory storeFactory = authorization.getStoreFactory();
+            Set<String> scopeNames = givenScopes.stream().map(ScopeRepresentation::getName).collect(Collectors.toSet());
 
             if (resource.getId() != null) {
-                Resource resourceModel = storeFactory.getResourceStore().findById(resource.getId());
-                return Permissions.createResourcePermissions(resourceModel, givenScopes, authorization).stream();
+                Resource resourceModel = storeFactory.getResourceStore().findById(resource.getId(), resourceServer.getId());
+                return Permissions.createResourcePermissions(resourceModel, scopeNames, authorization).stream();
             } else if (resource.getType() != null) {
-                Set<String> finalGivenScopes = givenScopes;
-                return storeFactory.getResourceStore().findByType(resource.getType()).stream().flatMap(resource1 -> Permissions.createResourcePermissions(resource1, finalGivenScopes, authorization).stream());
+                return storeFactory.getResourceStore().findByType(resource.getType(), resourceServer.getId()).stream().flatMap(resource1 -> Permissions.createResourcePermissions(resource1, scopeNames, authorization).stream());
             } else {
                 ScopeStore scopeStore = storeFactory.getScopeStore();
-                List<Scope> scopes = givenScopes.stream().map(scopeName -> scopeStore.findByName(scopeName, this.resourceServer.getId())).collect(Collectors.toList());
-                List<ResourcePermission> collect = scopes.stream().map(scope -> new ResourcePermission(null, asList(scope), resourceServer)).collect(Collectors.toList());
-
-                if (scopes.isEmpty()) {
-                    scopes = scopeStore.findByResourceServer(resourceServer.getId());
-                }
+                List<Scope> scopes = scopeNames.stream().map(scopeName -> scopeStore.findByName(scopeName, this.resourceServer.getId())).collect(Collectors.toList());
+                List<ResourcePermission> collect = new ArrayList<ResourcePermission>();
 
-                for (Scope scope : scopes) {
-                    collect.addAll(storeFactory.getResourceStore().findByScope(scope.getId()).stream().map(resource12 -> new ResourcePermission(resource12, asList(scope), resourceServer)).collect(Collectors.toList()));
+                if (!scopes.isEmpty()) {
+                    collect.addAll(scopes.stream().map(scope -> new ResourcePermission(null, asList(scope), resourceServer)).collect(Collectors.toList()));
+                } else {
+                    collect.addAll(Permissions.all(resourceServer, evaluationContext.getIdentity(), authorization));
                 }
 
-                collect.addAll(storeFactory.getResourceStore().findByResourceServer(resourceServer.getId()).stream().map(new Function<Resource, ResourcePermission>() {
-                    @Override
-                    public ResourcePermission apply(Resource resource) {
-                        return new ResourcePermission(resource, resource.getScopes(), resourceServer);
-                    }
-                }).collect(Collectors.toList()));
-
                 return collect.stream();
             }
         }).collect(Collectors.toList());
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
index e274bea..3caf2ea 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -17,6 +17,28 @@
  */
 package org.keycloak.authorization.admin;
 
+import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
+import static org.keycloak.models.utils.RepresentationToModel.toModel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.authorization.AuthorizationProvider;
@@ -25,35 +47,16 @@ import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
+import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.Constants;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.services.resources.admin.RealmAuth;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
-import static org.keycloak.models.utils.RepresentationToModel.toModel;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -100,7 +103,7 @@ public class PolicyService {
         this.auth.requireManage();
         representation.setId(id);
         StoreFactory storeFactory = authorization.getStoreFactory();
-        Policy policy = storeFactory.getPolicyStore().findById(representation.getId());
+        Policy policy = storeFactory.getPolicyStore().findById(representation.getId(), resourceServer.getId());
 
         if (policy == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -127,7 +130,7 @@ public class PolicyService {
         this.auth.requireManage();
         StoreFactory storeFactory = authorization.getStoreFactory();
         PolicyStore policyStore = storeFactory.getPolicyStore();
-        Policy policy = policyStore.findById(id);
+        Policy policy = policyStore.findById(id, resourceServer.getId());
 
         if (policy == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -143,7 +146,7 @@ public class PolicyService {
             }
         }
 
-        policyStore.findDependentPolicies(id).forEach(dependentPolicy -> {
+        policyStore.findDependentPolicies(id, resourceServer.getId()).forEach(dependentPolicy -> {
             if (dependentPolicy.getAssociatedPolicies().size() == 1) {
                 policyStore.delete(dependentPolicy.getId());
             } else {
@@ -163,13 +166,109 @@ public class PolicyService {
     public Response findById(@PathParam("id") String id) {
         this.auth.requireView();
         StoreFactory storeFactory = authorization.getStoreFactory();
-        Policy model = storeFactory.getPolicyStore().findById(id);
+        Policy model = storeFactory.getPolicyStore().findById(id, resourceServer.getId());
 
         if (model == null) {
             return Response.status(Status.NOT_FOUND).build();
         }
 
-        return Response.ok(toRepresentation(model, authorization)).build();
+        return Response.ok(toRepresentation(model)).build();
+    }
+
+    @Path("{id}/dependentPolicies")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getDependentPolicies(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Policy model = storeFactory.getPolicyStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        List<Policy> policies = authorization.getStoreFactory().getPolicyStore().findDependentPolicies(model.getId(), resourceServer.getId());
+
+        return Response.ok(policies.stream().map(policy -> {
+            PolicyRepresentation representation1 = new PolicyRepresentation();
+
+            representation1.setId(policy.getId());
+            representation1.setName(policy.getName());
+            representation1.setType(policy.getType());
+
+            return representation1;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("{id}/scopes")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getScopes(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Policy model = storeFactory.getPolicyStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        return Response.ok(model.getScopes().stream().map(scope -> {
+            ScopeRepresentation representation = new ScopeRepresentation();
+
+            representation.setId(scope.getId());
+            representation.setName(scope.getName());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("{id}/resources")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getResources(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Policy model = storeFactory.getPolicyStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        return Response.ok(model.getResources().stream().map(resource -> {
+            ResourceRepresentation representation = new ResourceRepresentation();
+
+            representation.setId(resource.getId());
+            representation.setName(resource.getName());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("{id}/associatedPolicies")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getAssociatedPolicies(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Policy model = storeFactory.getPolicyStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        return Response.ok(model.getAssociatedPolicies().stream().map(policy -> {
+            PolicyRepresentation representation1 = new PolicyRepresentation();
+
+            representation1.setId(policy.getId());
+            representation1.setName(policy.getName());
+            representation1.setType(policy.getType());
+
+            return representation1;
+        }).collect(Collectors.toList())).build();
     }
 
     @Path("/search")
@@ -190,13 +289,14 @@ public class PolicyService {
             return Response.status(Status.OK).build();
         }
 
-        return Response.ok(toRepresentation(model, authorization)).build();
+        return Response.ok(toRepresentation(model)).build();
     }
 
     @GET
     @Produces("application/json")
     @NoCache
-    public Response findAll(@QueryParam("name") String name,
+    public Response findAll(@QueryParam("policyId") String id,
+                            @QueryParam("name") String name,
                             @QueryParam("type") String type,
                             @QueryParam("resource") String resource,
                             @QueryParam("permission") Boolean permission,
@@ -206,6 +306,10 @@ public class PolicyService {
 
         Map<String, String[]> search = new HashMap<>();
 
+        if (id != null && !"".equals(id.trim())) {
+            search.put("id", new String[] {id});
+        }
+
         if (name != null && !"".equals(name.trim())) {
             search.put("name", new String[] {name});
         }
@@ -216,16 +320,17 @@ public class PolicyService {
 
         StoreFactory storeFactory = authorization.getStoreFactory();
 
+        PolicyStore policyStore = storeFactory.getPolicyStore();
         if (resource != null && !"".equals(resource.trim())) {
             List<Policy> policies = new ArrayList<>();
             HashMap<String, String[]> resourceSearch = new HashMap<>();
 
             resourceSearch.put("name", new String[] {resource});
 
-            storeFactory.getResourceStore().findByResourceServer(resourceSearch, resourceServer.getId(), -1, -1).forEach(resource1 -> {
-                ResourceRepresentation resourceRepresentation = ModelToRepresentation.toRepresentation(resource1, resourceServer, authorization);
-                resourceRepresentation.getPolicies().forEach(policyRepresentation -> {
-                    Policy associated = storeFactory.getPolicyStore().findById(policyRepresentation.getId());
+            ResourceStore resourceStore = storeFactory.getResourceStore();
+            resourceStore.findByResourceServer(resourceSearch, resourceServer.getId(), -1, -1).forEach(resource1 -> {
+                policyStore.findByResource(resource1.getId(), resourceServer.getId()).forEach(policyRepresentation -> {
+                    Policy associated = policyStore.findById(policyRepresentation.getId(), resourceServer.getId());
                     policies.add(associated);
                     findAssociatedPolicies(associated, policies);
                 });
@@ -243,8 +348,8 @@ public class PolicyService {
         }
 
         return Response.ok(
-                storeFactory.getPolicyStore().findByResourceServer(search, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
-                        .map(policy -> toRepresentation(policy, authorization))
+                policyStore.findByResourceServer(search, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
+                        .map(policy -> toRepresentation(policy))
                         .collect(Collectors.toList()))
                 .build();
     }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationRequest.java b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationRequest.java
index 17edef9..da7b420 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationRequest.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationRequest.java
@@ -22,6 +22,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -82,42 +84,7 @@ public class PolicyEvaluationRequest {
         this.entitlements = entitlements;
     }
 
-    public static class Resource {
-        private String id;
-        private String name;
-        private String type;
-        private Set<String> scopes;
-
-        public String getId() {
-            return this.id;
-        }
-
-        public void setId(String id) {
-            this.id = id;
-        }
-
-        public String getName() {
-            return this.name;
-        }
-
-        public void setName(String name) {
-            this.name = name;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public void setType(final String type) {
-            this.type = type;
-        }
-
-        public Set<String> getScopes() {
-            return scopes;
-        }
+    public static class Resource extends ResourceRepresentation {
 
-        public void setScopes(final Set<String> scopes) {
-            this.scopes = scopes;
-        }
     }
 }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
index 4f0c64a..83c00b8 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/representation/PolicyEvaluationResponse.java
@@ -35,9 +35,11 @@ import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -62,7 +64,7 @@ public class PolicyEvaluationResponse {
         AccessToken accessToken = identity.getAccessToken();
         AccessToken.Authorization authorizationData = new AccessToken.Authorization();
 
-        authorizationData.setPermissions(Permissions.allPermits(results, authorization));
+        authorizationData.setPermissions(Permissions.permits(results, authorization, resourceServer.getId()));
         accessToken.setAuthorization(authorizationData);
 
         response.rpt = accessToken;
@@ -80,7 +82,12 @@ public class PolicyEvaluationResponse {
             resultsRep.add(rep);
 
             if (result.getPermission().getResource() != null) {
-                rep.setResource(ModelToRepresentation.toRepresentation(result.getPermission().getResource(), resourceServer, authorization));
+                ResourceRepresentation resource = new ResourceRepresentation();
+
+                resource.setId(result.getPermission().getResource().getId());
+                resource.setName(result.getPermission().getResource().getName());
+
+                rep.setResource(resource);
             } else {
                 ResourceRepresentation resource = new ResourceRepresentation();
 
@@ -89,7 +96,14 @@ public class PolicyEvaluationResponse {
                 rep.setResource(resource);
             }
 
-            rep.setScopes(result.getPermission().getScopes().stream().map(scope -> ModelToRepresentation.toRepresentation(scope, authorization)).collect(Collectors.toList()));
+            rep.setScopes(result.getPermission().getScopes().stream().map(scope -> {
+                ScopeRepresentation representation = new ScopeRepresentation();
+
+                representation.setId(scope.getId());
+                representation.setName(scope.getName());
+
+                return representation;
+            }).collect(Collectors.toList()));
 
             List<PolicyResultRepresentation> policies = new ArrayList<>();
 
@@ -100,7 +114,7 @@ public class PolicyEvaluationResponse {
             rep.setPolicies(policies);
         }
 
-        resultsRep.sort((o1, o2) -> o1.getResource().getName().compareTo(o2.getResource().getName()));
+        resultsRep.sort(Comparator.comparing(o -> o.getResource().getName()));
 
         Map<String, EvaluationResultRepresentation> groupedResults = new HashMap<>();
 
@@ -127,17 +141,29 @@ public class PolicyEvaluationResponse {
             List<ScopeRepresentation> currentScopes = evaluationResultRepresentation.getScopes();
 
             if (currentScopes != null) {
+                List<ScopeRepresentation> allowedScopes = result.getAllowedScopes();
                 for (ScopeRepresentation scope : currentScopes) {
                     if (!scopes.contains(scope)) {
                         scopes.add(scope);
                     }
                     if (evaluationResultRepresentation.getStatus().equals(Effect.PERMIT)) {
-                        List<ScopeRepresentation> allowedScopes = result.getAllowedScopes();
                         if (!allowedScopes.contains(scope)) {
                             allowedScopes.add(scope);
                         }
+                    } else {
+                        evaluationResultRepresentation.getPolicies().forEach(new Consumer<PolicyResultRepresentation>() {
+                            @Override
+                            public void accept(PolicyResultRepresentation policyResultRepresentation) {
+                                if (policyResultRepresentation.getStatus().equals(Effect.PERMIT)) {
+                                    if (!allowedScopes.contains(scope)) {
+                                        allowedScopes.add(scope);
+                                    }
+                                }
+                            }
+                        });
                     }
                 }
+                result.setAllowedScopes(allowedScopes);
             }
 
             if (resource.getId() != null) {
@@ -160,18 +186,14 @@ public class PolicyEvaluationResponse {
                 }
 
                 if (policy.getStatus().equals(Effect.DENY)) {
-                    Policy policyModel = authorization.getStoreFactory().getPolicyStore().findById(policy.getPolicy().getId());
+                    Policy policyModel = authorization.getStoreFactory().getPolicyStore().findById(policy.getPolicy().getId(), resourceServer.getId());
                     for (ScopeRepresentation scope : policyModel.getScopes().stream().map(scopeModel -> ModelToRepresentation.toRepresentation(scopeModel, authorization)).collect(Collectors.toList())) {
-                        if (!policy.getScopes().contains(scope)) {
+                        if (!policy.getScopes().contains(scope) && policyModel.getScopes().stream().filter(policyScope -> policyScope.getId().equals(scope.getId())).findFirst().isPresent()) {
+                            result.getAllowedScopes().remove(scope);
                             policy.getScopes().add(scope);
                         }
                     }
-                    for (ScopeRepresentation scope : currentScopes) {
-                        if (!policy.getScopes().contains(scope)) {
-                            policy.getScopes().add(scope);
-                        }
-                    }
-                }
+                } else {}
             }
         });
 
@@ -183,7 +205,14 @@ public class PolicyEvaluationResponse {
     private static PolicyResultRepresentation toRepresentation(PolicyResult policy, AuthorizationProvider authorization) {
         PolicyResultRepresentation policyResultRep = new PolicyResultRepresentation();
 
-        policyResultRep.setPolicy(ModelToRepresentation.toRepresentation(policy.getPolicy(), authorization));
+        PolicyRepresentation representation = new PolicyRepresentation();
+
+        representation.setId(policy.getPolicy().getId());
+        representation.setName(policy.getPolicy().getName());
+        representation.setType(policy.getPolicy().getType());
+        representation.setDecisionStrategy(policy.getPolicy().getDecisionStrategy());
+
+        policyResultRep.setPolicy(representation);
         policyResultRep.setStatus(policy.getStatus());
         policyResultRep.setAssociatedPolicies(policy.getAssociatedPolicies().stream().map(result -> toRepresentation(result, authorization)).collect(Collectors.toList()));
 
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
index c1cb821..bb241d8 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
@@ -32,8 +32,10 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserProvider;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.RealmAuth;
 
@@ -48,10 +50,15 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
@@ -127,7 +134,7 @@ public class ResourceSetService {
         resource.setId(id);
         StoreFactory storeFactory = this.authorization.getStoreFactory();
         ResourceStore resourceStore = storeFactory.getResourceStore();
-        Resource model = resourceStore.findById(resource.getId());
+        Resource model = resourceStore.findById(resource.getId(), resourceServer.getId());
 
         if (model == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -143,14 +150,14 @@ public class ResourceSetService {
     public Response delete(@PathParam("id") String id) {
         requireManage();
         StoreFactory storeFactory = authorization.getStoreFactory();
-        Resource resource = storeFactory.getResourceStore().findById(id);
+        Resource resource = storeFactory.getResourceStore().findById(id, resourceServer.getId());
 
         if (resource == null) {
             return Response.status(Status.NOT_FOUND).build();
         }
 
         PolicyStore policyStore = storeFactory.getPolicyStore();
-        List<Policy> policies = policyStore.findByResource(id);
+        List<Policy> policies = policyStore.findByResource(id, resourceServer.getId());
 
         for (Policy policyModel : policies) {
             if (policyModel.getResources().size() == 1) {
@@ -172,13 +179,93 @@ public class ResourceSetService {
     public Response findById(@PathParam("id") String id) {
         requireView();
         StoreFactory storeFactory = authorization.getStoreFactory();
-        Resource model = storeFactory.getResourceStore().findById(id);
+        Resource model = storeFactory.getResourceStore().findById(id, resourceServer.getId());
 
         if (model == null) {
             return Response.status(Status.NOT_FOUND).build();
         }
 
-        return Response.ok(toRepresentation(model, this.resourceServer, authorization)).build();
+        return Response.ok(toRepresentation(model, this.resourceServer, authorization, true)).build();
+    }
+
+    @Path("{id}/scopes")
+    @GET
+    @NoCache
+    @Produces("application/json")
+    public Response getScopes(@PathParam("id") String id) {
+        requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Resource model = storeFactory.getResourceStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        List<ScopeRepresentation> scopes = model.getScopes().stream().map(scope -> {
+            ScopeRepresentation representation = new ScopeRepresentation();
+
+            representation.setId(scope.getId());
+            representation.setName(scope.getName());
+
+            return representation;
+        }).collect(Collectors.toList());
+
+        if (model.getType() != null) {
+            ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
+            for (Resource typed : resourceStore.findByType(model.getType(), resourceServer.getId())) {
+                if (typed.getOwner().equals(resourceServer.getClientId()) && !typed.getId().equals(model.getId())) {
+                    scopes.addAll(typed.getScopes().stream().map(model1 -> {
+                        ScopeRepresentation scope = new ScopeRepresentation();
+                        scope.setId(model1.getId());
+                        scope.setName(model1.getName());
+                        String iconUri = model1.getIconUri();
+                        if (iconUri != null) {
+                            scope.setIconUri(iconUri);
+                        }
+                        return scope;
+                    }).filter(scopeRepresentation -> !scopes.contains(scopeRepresentation)).collect(Collectors.toList()));
+                }
+            }
+        }
+
+        return Response.ok(scopes).build();
+    }
+
+    @Path("{id}/permissions")
+    @GET
+    @NoCache
+    @Produces("application/json")
+    public Response getPermissions(@PathParam("id") String id) {
+        requireView();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Resource model = storeFactory.getResourceStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
+        Set<Policy> policies = new HashSet<>();
+
+        policies.addAll(policyStore.findByResource(model.getId(), resourceServer.getId()));
+        policies.addAll(policyStore.findByResourceType(model.getType(), resourceServer.getId()));
+        policies.addAll(policyStore.findByScopeIds(model.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toList()), resourceServer.getId()));
+
+        List<PolicyRepresentation> representation = new ArrayList<>();
+
+        for (Policy policyModel : policies) {
+            PolicyRepresentation policy = new PolicyRepresentation();
+
+            policy.setId(policyModel.getId());
+            policy.setName(policyModel.getName());
+            policy.setType(policyModel.getType());
+
+            if (!representation.contains(policy)) {
+                representation.add(policy);
+            }
+        }
+
+        return Response.ok(representation).build();
     }
 
     @Path("/search")
@@ -205,18 +292,29 @@ public class ResourceSetService {
     @GET
     @NoCache
     @Produces("application/json")
-    public Response find(@QueryParam("name") String name,
+    public Response find(@QueryParam("_id") String id,
+                            @QueryParam("name") String name,
                             @QueryParam("uri") String uri,
                             @QueryParam("owner") String owner,
                             @QueryParam("type") String type,
                             @QueryParam("scope") String scope,
+                            @QueryParam("deep") Boolean deep,
                             @QueryParam("first") Integer firstResult,
                             @QueryParam("max") Integer maxResult) {
         requireView();
+
         StoreFactory storeFactory = authorization.getStoreFactory();
 
+        if (deep == null) {
+            deep = true;
+        }
+
         Map<String, String[]> search = new HashMap<>();
 
+        if (id != null && !"".equals(id.trim())) {
+            search.put("id", new String[] {id});
+        }
+
         if (name != null && !"".equals(name.trim())) {
             search.put("name", new String[] {name});
         }
@@ -260,9 +358,10 @@ public class ResourceSetService {
             search.put("scope", scopes.stream().map(Scope::getId).toArray(String[]::new));
         }
 
+        Boolean finalDeep = deep;
         return Response.ok(
                 storeFactory.getResourceStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
-                        .map(resource -> toRepresentation(resource, this.resourceServer, authorization))
+                        .map(resource -> toRepresentation(resource, resourceServer, authorization, finalDeep))
                         .collect(Collectors.toList()))
                 .build();
     }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
index 83cffeb..7724830 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -26,6 +26,8 @@ import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.Constants;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.RealmAuth;
@@ -41,6 +43,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -85,7 +88,7 @@ public class ScopeService {
         this.auth.requireManage();
         scope.setId(id);
         StoreFactory storeFactory = authorization.getStoreFactory();
-        Scope model = storeFactory.getScopeStore().findById(scope.getId());
+        Scope model = storeFactory.getScopeStore().findById(scope.getId(), resourceServer.getId());
 
         if (model == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -101,13 +104,13 @@ public class ScopeService {
     public Response delete(@PathParam("id") String id) {
         this.auth.requireManage();
         StoreFactory storeFactory = authorization.getStoreFactory();
-        List<Resource> resources = storeFactory.getResourceStore().findByScope(id);
+        List<Resource> resources = storeFactory.getResourceStore().findByScope(Arrays.asList(id), resourceServer.getId());
 
         if (!resources.isEmpty()) {
             return ErrorResponse.exists("Scopes can not be removed while associated with resources.");
         }
 
-        Scope scope = storeFactory.getScopeStore().findById(id);
+        Scope scope = storeFactory.getScopeStore().findById(id, resourceServer.getId());
 
         if (scope == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -134,7 +137,7 @@ public class ScopeService {
     @Produces("application/json")
     public Response findById(@PathParam("id") String id) {
         this.auth.requireView();
-        Scope model = this.authorization.getStoreFactory().getScopeStore().findById(id);
+        Scope model = this.authorization.getStoreFactory().getScopeStore().findById(id, resourceServer.getId());
 
         if (model == null) {
             return Response.status(Status.NOT_FOUND).build();
@@ -143,6 +146,53 @@ public class ScopeService {
         return Response.ok(toRepresentation(model, this.authorization)).build();
     }
 
+    @Path("{id}/resources")
+    @GET
+    @Produces("application/json")
+    public Response getResources(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = this.authorization.getStoreFactory();
+        Scope model = storeFactory.getScopeStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        return Response.ok(storeFactory.getResourceStore().findByScope(Arrays.asList(model.getId()), resourceServer.getId()).stream().map(resource -> {
+            ResourceRepresentation representation = new ResourceRepresentation();
+
+            representation.setId(resource.getId());
+            representation.setName(resource.getName());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("{id}/permissions")
+    @GET
+    @Produces("application/json")
+    public Response getPermissions(@PathParam("id") String id) {
+        this.auth.requireView();
+        StoreFactory storeFactory = this.authorization.getStoreFactory();
+        Scope model = storeFactory.getScopeStore().findById(id, resourceServer.getId());
+
+        if (model == null) {
+            return Response.status(Status.NOT_FOUND).build();
+        }
+
+        PolicyStore policyStore = storeFactory.getPolicyStore();
+
+        return Response.ok(policyStore.findByScopeIds(Arrays.asList(model.getId()), resourceServer.getId()).stream().map(policy -> {
+            PolicyRepresentation representation = new PolicyRepresentation();
+
+            representation.setId(policy.getId());
+            representation.setName(policy.getName());
+            representation.setType(policy.getType());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
     @Path("/search")
     @GET
     @Produces("application/json")
@@ -166,20 +216,31 @@ public class ScopeService {
 
     @GET
     @Produces("application/json")
-    public Response findAll(@QueryParam("name") String name,
+    public Response findAll(@QueryParam("scopeId") String id,
+                            @QueryParam("name") String name,
+                            @QueryParam("deep") Boolean deep,
                             @QueryParam("first") Integer firstResult,
                             @QueryParam("max") Integer maxResult) {
         this.auth.requireView();
 
+        if (deep == null) {
+            deep = true;
+        }
+
         Map<String, String[]> search = new HashMap<>();
 
+        if (id != null && !"".equals(id.trim())) {
+            search.put("id", new String[] {id});
+        }
+
         if (name != null && !"".equals(name.trim())) {
             search.put("name", new String[] {name});
         }
 
+        Boolean finalDeep = deep;
         return Response.ok(
                 this.authorization.getStoreFactory().getScopeStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
-                        .map(scope -> toRepresentation(scope, this.authorization))
+                        .map(scope -> toRepresentation(scope, this.authorization, finalDeep))
                         .collect(Collectors.toList()))
                 .build();
     }
diff --git a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
index 77a35e9..e60a0d6 100644
--- a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
+++ b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
@@ -110,7 +110,7 @@ public class AuthorizationTokenService {
         authorization.evaluators().from(createPermissions(ticket, authorizationRequest, authorization), evaluationContext).evaluate(new DecisionResultCollector() {
             @Override
             public void onComplete(List<Result> results) {
-                List<Permission> entitlements = Permissions.allPermits(results, authorization);
+                List<Permission> entitlements = Permissions.permits(results, authorization, ticket.getResourceServerId());
 
                 if (entitlements.isEmpty()) {
                     HashMap<Object, Object> error = new HashMap<>();
@@ -144,7 +144,7 @@ public class AuthorizationTokenService {
             Resource resource;
 
             if (requestedResource.getId() != null) {
-                resource = storeFactory.getResourceStore().findById(requestedResource.getId());
+                resource = storeFactory.getResourceStore().findById(requestedResource.getId(), ticket.getResourceServerId());
             } else {
                 resource = storeFactory.getResourceStore().findByName(requestedResource.getName(), ticket.getResourceServerId());
             }
@@ -171,7 +171,7 @@ public class AuthorizationTokenService {
                     }
 
                     return scope.getId();
-                }).filter(s -> s != null).collect(Collectors.toList()).toArray(new String[requestedScopes.size()])));
+                }).filter(s -> s != null).collect(Collectors.toList()), ticket.getResourceServerId()));
 
                 for (Resource resource1 : resources) {
                     permissionsToEvaluate.put(resource1.getId(), collect);
@@ -204,7 +204,7 @@ public class AuthorizationTokenService {
 
                     if (permissions != null) {
                         permissions.forEach(permission -> {
-                            Resource resourcePermission = storeFactory.getResourceStore().findById(permission.getResourceSetId());
+                            Resource resourcePermission = storeFactory.getResourceStore().findById(permission.getResourceSetId(), ticket.getResourceServerId());
 
                             if (resourcePermission != null) {
                                 Set<String> scopes = permissionsToEvaluate.get(resourcePermission.getId());
@@ -240,7 +240,7 @@ public class AuthorizationTokenService {
                         }).collect(Collectors.toList());
                         return Arrays.asList(new ResourcePermission(null, scopes, resourceServer)).stream();
                     } else {
-                        Resource entryResource = storeFactory.getResourceStore().findById(key);
+                        Resource entryResource = storeFactory.getResourceStore().findById(key, resourceServer.getId());
                         return Permissions.createResourcePermissions(entryResource, entry.getValue(), authorization).stream();
                     }
                 }).collect(Collectors.toList());
diff --git a/services/src/main/java/org/keycloak/authorization/DefaultAuthorizationProviderFactory.java b/services/src/main/java/org/keycloak/authorization/DefaultAuthorizationProviderFactory.java
index 6146594..159e5aa 100644
--- a/services/src/main/java/org/keycloak/authorization/DefaultAuthorizationProviderFactory.java
+++ b/services/src/main/java/org/keycloak/authorization/DefaultAuthorizationProviderFactory.java
@@ -18,14 +18,20 @@
 
 package org.keycloak.authorization;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
 import org.keycloak.Config;
+import org.keycloak.authorization.policy.provider.PolicyProvider;
+import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
-
-import java.util.concurrent.Executor;
+import org.keycloak.provider.ProviderFactory;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -33,6 +39,7 @@ import java.util.concurrent.Executor;
 public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory {
 
     private Executor scheduler;
+    private Map<String, PolicyProviderFactory> policyProviderFactories;
 
     @Override
     public AuthorizationProvider create(KeycloakSession session) {
@@ -54,6 +61,7 @@ public class DefaultAuthorizationProviderFactory implements AuthorizationProvide
 
     @Override
     public void postInit(KeycloakSessionFactory factory) {
+        policyProviderFactories = configurePolicyProviderFactories(factory);
     }
 
     @Override
@@ -74,6 +82,21 @@ public class DefaultAuthorizationProviderFactory implements AuthorizationProvide
             storeFactory = session.getProvider(StoreFactory.class);
         }
 
-        return new AuthorizationProvider(session, realm, storeFactory);
+        return new AuthorizationProvider(session, realm, storeFactory, policyProviderFactories);
+    }
+
+    private Map<String, PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSessionFactory keycloakSessionFactory) {
+        List<ProviderFactory> providerFactories = keycloakSessionFactory.getProviderFactories(PolicyProvider.class);
+
+        if (providerFactories.isEmpty()) {
+            throw new RuntimeException("Could not find any policy provider.");
+        }
+
+        HashMap<String, PolicyProviderFactory> providers = new HashMap<>();
+
+        providerFactories.forEach(providerFactory -> providers.put(providerFactory.getId(), (PolicyProviderFactory) providerFactory));
+
+        return providers;
     }
+
 }
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/authorization/entitlement/EntitlementService.java b/services/src/main/java/org/keycloak/authorization/entitlement/EntitlementService.java
index 9f89e4a..579417d 100644
--- a/services/src/main/java/org/keycloak/authorization/entitlement/EntitlementService.java
+++ b/services/src/main/java/org/keycloak/authorization/entitlement/EntitlementService.java
@@ -46,6 +46,7 @@ import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.authorization.Permission;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.resources.Cors;
 
@@ -125,7 +126,7 @@ public class EntitlementService {
 
             @Override
             protected void onComplete(List<Result> results) {
-                List<Permission> entitlements = Permissions.allPermits(results, authorization);
+                List<Permission> entitlements = Permissions.allPermits(results, authorization, resourceServer);
 
                 if (entitlements.isEmpty()) {
                     HashMap<Object, Object> error = new HashMap<>();
@@ -169,31 +170,40 @@ public class EntitlementService {
         StoreFactory storeFactory = authorization.getStoreFactory();
         ResourceServer resourceServer = storeFactory.getResourceServerStore().findByClient(client.getId());
 
-        authorization.evaluators().from(createPermissions(entitlementRequest, resourceServer, authorization), new KeycloakEvaluationContext(this.authorization.getKeycloakSession())).evaluate(new DecisionResultCollector() {
-
-            @Override
-            public void onError(Throwable cause) {
-                asyncResponse.resume(cause);
-            }
+        try {
+            authorization.evaluators().from(createPermissions(entitlementRequest, resourceServer, authorization), new KeycloakEvaluationContext(this.authorization.getKeycloakSession())).evaluate(new DecisionResultCollector() {
+                @Override
+                public void onError(Throwable cause) {
+                    asyncResponse.resume(cause);
+                }
 
-            @Override
-            protected void onComplete(List<Result> results) {
-                List<Permission> entitlements = Permissions.allPermits(results, authorization);
+                @Override
+                protected void onComplete(List<Result> results) {
+                    List<Permission> entitlements = Permissions.allPermits(results, authorization, resourceServer);
 
-                if (entitlements.isEmpty()) {
-                    HashMap<Object, Object> error = new HashMap<>();
+                    if (entitlements.isEmpty()) {
+                        HashMap<Object, Object> error = new HashMap<>();
 
-                    error.put(OAuth2Constants.ERROR, "not_authorized");
+                        error.put(OAuth2Constants.ERROR, "not_authorized");
 
-                    asyncResponse.resume(Cors.add(request, Response.status(Status.FORBIDDEN)
-                            .entity(error))
-                            .allowedOrigins(identity.getAccessToken())
-                            .exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build());
-                } else {
-                    asyncResponse.resume(Cors.add(request, Response.ok().entity(new EntitlementResponse(createRequestingPartyToken(entitlements)))).allowedOrigins(identity.getAccessToken()).allowedMethods("GET").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build());
+                        asyncResponse.resume(Cors.add(request, Response.status(Status.FORBIDDEN)
+                                .entity(error))
+                                .allowedOrigins(identity.getAccessToken())
+                                .exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build());
+                    } else {
+                        asyncResponse.resume(Cors.add(request, Response.ok().entity(new EntitlementResponse(createRequestingPartyToken(entitlements)))).allowedOrigins(identity.getAccessToken()).allowedMethods("GET").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build());
+                    }
                 }
+            });
+        } catch (Exception e) {
+            String message = e.getMessage();
+
+            if (message == null) {
+                message = "Could not process authorization request";
             }
-        });
+
+            asyncResponse.resume(ErrorResponse.error(message, Status.BAD_REQUEST));
+        }
     }
 
     private String createRequestingPartyToken(List<Permission> permissions) {
@@ -215,7 +225,7 @@ public class EntitlementService {
             Resource resource;
 
             if (requestedResource.getResourceSetId() != null) {
-                resource = storeFactory.getResourceStore().findById(requestedResource.getResourceSetId());
+                resource = storeFactory.getResourceStore().findById(requestedResource.getResourceSetId(), resourceServer.getId());
             } else {
                 resource = storeFactory.getResourceStore().findByName(requestedResource.getResourceSetName(), resourceServer.getId());
             }
@@ -242,7 +252,7 @@ public class EntitlementService {
                     }
 
                     return scope.getId();
-                }).filter(s -> s != null).collect(Collectors.toList()).toArray(new String[requestedScopes.size()])));
+                }).filter(s -> s != null).collect(Collectors.toList()), resourceServer.getId()));
 
                 for (Resource resource1 : resources) {
                     permissionsToEvaluate.put(resource1.getId(), collect);
@@ -276,7 +286,7 @@ public class EntitlementService {
 
                     if (permissions != null) {
                         permissions.forEach(permission -> {
-                            Resource resourcePermission = storeFactory.getResourceStore().findById(permission.getResourceSetId());
+                            Resource resourcePermission = storeFactory.getResourceStore().findById(permission.getResourceSetId(), resourceServer.getId());
 
                             if (resourcePermission != null) {
                                 Set<String> scopes = permissionsToEvaluate.get(resourcePermission.getId());
@@ -310,7 +320,7 @@ public class EntitlementService {
                         }).collect(Collectors.toList());
                         return Arrays.asList(new ResourcePermission(null, scopes, resourceServer)).stream();
                     } else {
-                        Resource entryResource = storeFactory.getResourceStore().findById(key);
+                        Resource entryResource = storeFactory.getResourceStore().findById(key, resourceServer.getId());
                         return Permissions.createResourcePermissions(entryResource, entry.getValue(), authorization).stream();
                     }
                 }).collect(Collectors.toList());
diff --git a/services/src/main/java/org/keycloak/authorization/protection/permission/AbstractPermissionService.java b/services/src/main/java/org/keycloak/authorization/protection/permission/AbstractPermissionService.java
index a412c0c..80fb84a 100644
--- a/services/src/main/java/org/keycloak/authorization/protection/permission/AbstractPermissionService.java
+++ b/services/src/main/java/org/keycloak/authorization/protection/permission/AbstractPermissionService.java
@@ -77,7 +77,7 @@ public class AbstractPermissionService {
 
             if (!resourceNotProvider) {
                 if (resourceSetId != null) {
-                    resource = storeFactory.getResourceStore().findById(resourceSetId);
+                    resource = storeFactory.getResourceStore().findById(resourceSetId, resourceServer.getId());
                 } else {
                     resource = storeFactory.getResourceStore().findByName(resourceSetName, this.resourceServer.getId());
                 }
@@ -113,7 +113,7 @@ public class AbstractPermissionService {
                     }
                 }
 
-                for (Resource baseResource : authorization.getStoreFactory().getResourceStore().findByType(resource.getType())) {
+                for (Resource baseResource : authorization.getStoreFactory().getResourceStore().findByType(resource.getType(), resourceServer.getId())) {
                     if (baseResource.getOwner().equals(resource.getResourceServer().getClientId())) {
                         for (Scope baseScope : baseResource.getScopes()) {
                             if (baseScope.getName().equals(scopeName)) {
diff --git a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
index fdaa12f..219bcca 100644
--- a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
+++ b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
@@ -109,7 +109,7 @@ public class ResourceService {
     }
 
     private Set<String> findAll() {
-        Response response = this.resourceManager.find(null, null, null, null, null, -1, -1);
+        Response response = this.resourceManager.find(null, null, null, null, null, null, true, -1, -1);
         List<ResourceRepresentation> resources = (List<ResourceRepresentation>) response.getEntity();
         return resources.stream().map(ResourceRepresentation::getId).collect(Collectors.toSet());
     }
@@ -150,7 +150,7 @@ public class ResourceService {
                 }
             }
         } else {
-            resources = storeFactory.getResourceStore().findByOwner(identity.getId()).stream()
+            resources = storeFactory.getResourceStore().findByOwner(identity.getId(), resourceServer.getId()).stream()
                     .map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
                     .collect(Collectors.toSet());
         }
diff --git a/services/src/main/java/org/keycloak/authorization/util/Permissions.java b/services/src/main/java/org/keycloak/authorization/util/Permissions.java
index 116ddd6..90de912 100644
--- a/services/src/main/java/org/keycloak/authorization/util/Permissions.java
+++ b/services/src/main/java/org/keycloak/authorization/util/Permissions.java
@@ -18,9 +18,18 @@
 
 package org.keycloak.authorization.util;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.Decision.Effect;
 import org.keycloak.authorization.identity.Identity;
+import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
@@ -31,16 +40,6 @@ import org.keycloak.authorization.store.ScopeStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.representations.idm.authorization.Permission;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -62,8 +61,8 @@ public final class Permissions {
         StoreFactory storeFactory = authorization.getStoreFactory();
         ResourceStore resourceStore = storeFactory.getResourceStore();
 
-        resourceStore.findByOwner(resourceServer.getClientId()).stream().forEach(resource -> permissions.addAll(createResourcePermissions(resource, resource.getScopes().stream().map(Scope::getName).collect(Collectors.toSet()), authorization)));
-        resourceStore.findByOwner(identity.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissions(resource, resource.getScopes().stream().map(Scope::getName).collect(Collectors.toSet()), authorization)));
+        resourceStore.findByOwner(resourceServer.getClientId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, resource.getScopes(), authorization)));
+        resourceStore.findByOwner(identity.getId(), resourceServer.getId()).stream().forEach(resource -> permissions.addAll(createResourcePermissionsWithScopes(resource, resource.getScopes(), authorization)));
 
         return permissions;
     }
@@ -81,7 +80,7 @@ public final class Permissions {
             if (type != null && !resource.getOwner().equals(resourceServer.getClientId())) {
                 StoreFactory storeFactory = authorization.getStoreFactory();
                 ResourceStore resourceStore = storeFactory.getResourceStore();
-                resourceStore.findByType(type).forEach(resource1 -> {
+                resourceStore.findByType(type, resourceServer.getId()).forEach(resource1 -> {
                     if (resource1.getOwner().equals(resourceServer.getClientId())) {
                         for (Scope typeScope : resource1.getScopes()) {
                             if (!scopes.contains(typeScope)) {
@@ -95,78 +94,141 @@ public final class Permissions {
             ScopeStore scopeStore = authorization.getStoreFactory().getScopeStore();
             scopes = requestedScopes.stream().map(scopeName -> {
                 Scope byName = scopeStore.findByName(scopeName, resource.getResourceServer().getId());
+
+                if (byName == null) {
+                    throw new RuntimeException("Invalid scope [" + scopeName + "].");
+                }
+
                 return byName;
             }).collect(Collectors.toList());
         }
 
-        if (scopes.isEmpty()) {
-            permissions.add(new ResourcePermission(resource, Collections.emptyList(), resource.getResourceServer()));
-        } else {
-            for (Scope scope : scopes) {
-                permissions.add(new ResourcePermission(resource, Arrays.asList(scope), resource.getResourceServer()));
-            }
+        permissions.add(new ResourcePermission(resource, scopes, resource.getResourceServer()));
+
+        return permissions;
+    }
+
+    public static List<ResourcePermission> createResourcePermissionsWithScopes(Resource resource, List<Scope> scopes, AuthorizationProvider authorization) {
+        List<ResourcePermission> permissions = new ArrayList<>();
+        String type = resource.getType();
+        ResourceServer resourceServer = resource.getResourceServer();
+
+        // check if there is a typed resource whose scopes are inherited by the resource being requested. In this case, we assume that parent resource
+        // is owned by the resource server itself
+        if (type != null && !resource.getOwner().equals(resourceServer.getClientId())) {
+            StoreFactory storeFactory = authorization.getStoreFactory();
+            ResourceStore resourceStore = storeFactory.getResourceStore();
+            resourceStore.findByType(type, resourceServer.getId()).forEach(resource1 -> {
+                if (resource1.getOwner().equals(resourceServer.getClientId())) {
+                    for (Scope typeScope : resource1.getScopes()) {
+                        if (!scopes.contains(typeScope)) {
+                            scopes.add(typeScope);
+                        }
+                    }
+                }
+            });
         }
 
+        permissions.add(new ResourcePermission(resource, scopes, resource.getResourceServer()));
+
         return permissions;
     }
 
-    public static List<Permission> allPermits(List<Result> evaluation, AuthorizationProvider authorizationProvider) {
+    public static List<Permission> allPermits(List<Result> evaluation, AuthorizationProvider authorizationProvider, ResourceServer resourceServer) {
+        Map<String, Permission> permissions = new HashMap<>();
+
+        for (Result evaluationResult : evaluation) {
+            ResourcePermission permission = evaluationResult.getPermission();
+
+            // if overall decision was a DENY, check for scope-based policies for a PERMIT
+            if (evaluationResult.getEffect().equals(Effect.DENY)) {
+                for (Result.PolicyResult result : evaluationResult.getResults()) {
+                    Policy policy = result.getPolicy();
+
+                    if ("scope".equals(policy.getType())) {
+                        Set<Resource> resources = policy.getResources();
+
+                        if (Effect.PERMIT.equals(result.getStatus())) {
+                            List<Scope> scopes = policy.getScopes().stream().collect(Collectors.toList());
+
+                            if (!resources.isEmpty()) {
+                                resources.forEach(resource -> grantPermission(authorizationProvider, permissions, new ResourcePermission(resource, scopes, policy.getResourceServer()), resourceServer.getId()));
+                            } else {
+                                grantPermission(authorizationProvider, permissions, new ResourcePermission(permission.getResource(), scopes, policy.getResourceServer()), resourceServer.getId());
+                            }
+                        }
+                    }
+                }
+                continue;
+            }
+
+            grantPermission(authorizationProvider, permissions, permission, resourceServer.getId());
+        }
+
+        return permissions.values().stream().collect(Collectors.toList());
+    }
+
+    public static List<Permission> permits(List<Result> evaluation, AuthorizationProvider authorizationProvider, String resourceServer) {
         Map<String, Permission> permissions = new HashMap<>();
 
         for (Result evaluationResult : evaluation) {
             ResourcePermission permission = evaluationResult.getPermission();
-            Set<String> scopes = permission.getScopes().stream().map(Scope::getName).collect(Collectors.toSet());
 
             if (evaluationResult.getEffect().equals(Effect.DENY)) {
                 continue;
             }
 
-            List<Resource> resources = new ArrayList<>();
-            Resource resource = permission.getResource();
+            grantPermission(authorizationProvider, permissions, permission, resourceServer);
+        }
 
-            if (resource != null) {
-                resources.add(resource);
-            } else {
-                List<Scope> permissionScopes = permission.getScopes();
+        return permissions.values().stream().collect(Collectors.toList());
+    }
 
-                if (!permissionScopes.isEmpty()) {
-                    ResourceStore resourceStore = authorizationProvider.getStoreFactory().getResourceStore();
-                    resources.addAll(resourceStore.findByScope(permissionScopes.stream().map(Scope::getId).collect(Collectors.toList()).toArray(new String[permissionScopes.size()])));
-                }
+    private static void grantPermission(AuthorizationProvider authorizationProvider, Map<String, Permission> permissions, ResourcePermission permission, String resourceServer) {
+        List<Resource> resources = new ArrayList<>();
+        Resource resource = permission.getResource();
+        Set<String> scopes = permission.getScopes().stream().map(Scope::getName).collect(Collectors.toSet());
+
+        if (resource != null) {
+            resources.add(resource);
+        } else {
+            List<Scope> permissionScopes = permission.getScopes();
+
+            if (!permissionScopes.isEmpty()) {
+                ResourceStore resourceStore = authorizationProvider.getStoreFactory().getResourceStore();
+                resources.addAll(resourceStore.findByScope(permissionScopes.stream().map(Scope::getId).collect(Collectors.toList()), resourceServer));
             }
+        }
 
-            if (!resources.isEmpty()) {
-                for (Resource allowedResource : resources) {
-                    String resourceId = allowedResource.getId();
-                    String resourceName = allowedResource.getName();
-                    Permission evalPermission = permissions.get(allowedResource.getId());
+        if (!resources.isEmpty()) {
+            for (Resource allowedResource : resources) {
+                String resourceId = allowedResource.getId();
+                String resourceName = allowedResource.getName();
+                Permission evalPermission = permissions.get(allowedResource.getId());
 
-                    if (evalPermission == null) {
-                        evalPermission = new Permission(resourceId, resourceName, scopes);
-                        permissions.put(resourceId, evalPermission);
-                    }
+                if (evalPermission == null) {
+                    evalPermission = new Permission(resourceId, resourceName, scopes);
+                    permissions.put(resourceId, evalPermission);
+                }
 
-                    if (scopes != null && !scopes.isEmpty()) {
-                        Set<String> finalScopes = evalPermission.getScopes();
+                if (scopes != null && !scopes.isEmpty()) {
+                    Set<String> finalScopes = evalPermission.getScopes();
 
-                        if (finalScopes == null) {
-                            finalScopes = new HashSet();
-                            evalPermission.setScopes(finalScopes);
-                        }
+                    if (finalScopes == null) {
+                        finalScopes = new HashSet();
+                        evalPermission.setScopes(finalScopes);
+                    }
 
-                        for (String scopeName : scopes) {
-                            if (!finalScopes.contains(scopeName)) {
-                                finalScopes.add(scopeName);
-                            }
+                    for (String scopeName : scopes) {
+                        if (!finalScopes.contains(scopeName)) {
+                            finalScopes.add(scopeName);
                         }
                     }
                 }
-            } else {
-                Permission scopePermission = new Permission(null, null, scopes);
-                permissions.put(scopePermission.toString(), scopePermission);
             }
+        } else {
+            Permission scopePermission = new Permission(null, null, scopes);
+            permissions.put(scopePermission.toString(), scopePermission);
         }
-
-        return permissions.values().stream().collect(Collectors.toList());
     }
 }
diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index df7f8d3..29b8942 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -17,18 +17,27 @@
 
 package org.keycloak.exportimport.util;
 
-import com.fasterxml.jackson.core.JsonEncoding;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
+import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.AuthorizationProviderFactory;
 import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.PolicyStore;
-import org.keycloak.authorization.store.ResourceStore;
-import org.keycloak.authorization.store.ScopeStore;
 import org.keycloak.authorization.store.StoreFactory;
 import org.keycloak.common.Version;
 import org.keycloak.common.util.Base64;
@@ -63,20 +72,11 @@ import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
 import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
+import com.fasterxml.jackson.core.JsonEncoding;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -295,7 +295,6 @@ public class ExportUtils {
                         rep.getOwner().setId(null);
                     }
                     rep.setId(null);
-                    rep.setPolicies(null);
                     rep.getScopes().forEach(scopeRepresentation -> {
                         scopeRepresentation.setId(null);
                         scopeRepresentation.setIconUri(null);
@@ -338,10 +337,9 @@ public class ExportUtils {
         RealmModel realm = authorizationProvider.getRealm();
         StoreFactory storeFactory = authorizationProvider.getStoreFactory();
         try {
-            PolicyRepresentation rep = toRepresentation(policy, authorizationProvider);
+            PolicyRepresentation rep = toRepresentation(policy);
 
             rep.setId(null);
-            rep.setDependentPolicies(null);
 
             Map<String, String> config = rep.getConfig();
 
@@ -363,20 +361,18 @@ public class ExportUtils {
                 config.put("users", JsonSerialization.writeValueAsString(userIds.stream().map(userId -> userManager.getUserById(userId, realm).getUsername()).collect(Collectors.toList())));
             }
 
-            String scopes = config.get("scopes");
+            Set<Scope> scopes = policy.getScopes();
 
-            if (scopes != null && !scopes.isEmpty()) {
-                ScopeStore scopeStore = storeFactory.getScopeStore();
-                List<String> scopeIds = JsonSerialization.readValue(scopes, List.class);
-                config.put("scopes", JsonSerialization.writeValueAsString(scopeIds.stream().map(scopeId -> scopeStore.findById(scopeId).getName()).collect(Collectors.toList())));
+            if (!scopes.isEmpty()) {
+                List<String> scopeNames = scopes.stream().map(Scope::getName).collect(Collectors.toList());
+                config.put("scopes", JsonSerialization.writeValueAsString(scopeNames));
             }
 
-            String policyResources = config.get("resources");
+            Set<Resource> policyResources = policy.getResources();
 
-            if (policyResources != null && !policyResources.isEmpty()) {
-                ResourceStore resourceStore = storeFactory.getResourceStore();
-                List<String> resourceIds = JsonSerialization.readValue(policyResources, List.class);
-                config.put("resources", JsonSerialization.writeValueAsString(resourceIds.stream().map(resourceId -> resourceStore.findById(resourceId).getName()).collect(Collectors.toList())));
+            if (!policyResources.isEmpty()) {
+                List<String> resourceNames = scopes.stream().map(Scope::getName).collect(Collectors.toList());
+                config.put("resources", JsonSerialization.writeValueAsString(resourceNames));
             }
 
             Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
@@ -385,8 +381,6 @@ public class ExportUtils {
                 config.put("applyPolicies", JsonSerialization.writeValueAsString(associatedPolicies.stream().map(associated -> associated.getName()).collect(Collectors.toList())));
             }
 
-            rep.setAssociatedPolicies(null);
-
             return rep;
         } catch (Exception e) {
             throw new RuntimeException("Error while exporting policy [" + policy.getName() + "].", e);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractPhotozAdminTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractPhotozAdminTest.java
index c9b69d8..c46b338 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractPhotozAdminTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractPhotozAdminTest.java
@@ -101,7 +101,7 @@ public abstract class AbstractPhotozAdminTest extends AbstractAuthorizationTest 
 
             // during tests we create resource instances, but we need to reload them to get their collections updated
             List<ResourcePermission> updatedPermissions = permissions.stream().map(permission -> {
-                Resource resource = storeFactory.getResourceStore().findById(permission.getResource().getId());
+                Resource resource = storeFactory.getResourceStore().findById(permission.getResource().getId(), resourceServer.getId());
                 return new ResourcePermission(resource, permission.getScopes(), permission.getResourceServer());
             }).collect(Collectors.toList());
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourceManagementTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourceManagementTest.java
index 086b5ac..4a4fc9a 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourceManagementTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourceManagementTest.java
@@ -53,7 +53,7 @@ public class ResourceManagementTest extends AbstractPhotozAdminTest {
         ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId());
+            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId(), resourceServer.getId());
 
             assertNotNull(resourceModel);
             assertEquals(resource.getId(), resourceModel.getId());
@@ -89,7 +89,7 @@ public class ResourceManagementTest extends AbstractPhotozAdminTest {
         ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId());
+            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId(), resourceServer.getId());
 
             assertNotNull(resourceModel);
             assertEquals(resource.getId(), resourceModel.getId());
@@ -147,7 +147,7 @@ public class ResourceManagementTest extends AbstractPhotozAdminTest {
         assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
 
         onAuthorizationSession(authorizationProvider -> {
-            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId());
+            Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId(), resourceServer.getId());
 
             assertNull(resourceModel);
         });
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourcePermissionManagementTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourcePermissionManagementTest.java
index 9ecbc3d..4708a2a 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourcePermissionManagementTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ResourcePermissionManagementTest.java
@@ -46,8 +46,12 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -77,7 +81,7 @@ public class ResourcePermissionManagementTest extends AbstractPhotozAdminTest {
         PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId());
+            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
 
             assertNotNull(policyModel);
             assertEquals(permission.getId(), policyModel.getId());
@@ -357,7 +361,7 @@ public class ResourcePermissionManagementTest extends AbstractPhotozAdminTest {
         PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId());
+            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
 
             assertNotNull(policyModel);
             assertEquals(permission.getId(), policyModel.getId());
@@ -430,7 +434,8 @@ public class ResourcePermissionManagementTest extends AbstractPhotozAdminTest {
 
         config.put("defaultResourceType",  albumResource.getType());
 
-        String applyPolicies = JsonSerialization.writeValueAsString(new String[]{this.anyUserPolicy.getId(), this.administrationPolicy.getId()});
+        String[] associatedPolicies = {this.anyUserPolicy.getId(), this.administrationPolicy.getId()};
+        String applyPolicies = JsonSerialization.writeValueAsString(associatedPolicies);
 
         config.put("applyPolicies", applyPolicies);
 
@@ -443,14 +448,15 @@ public class ResourcePermissionManagementTest extends AbstractPhotozAdminTest {
         PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId());
+            Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
 
             assertNotNull(policyModel);
             assertEquals(permission.getId(), policyModel.getId());
             assertEquals(permission.getName(), policyModel.getName());
             assertEquals(permission.getType(), policyModel.getType());
             assertTrue(permission.getConfig().containsValue(albumResource.getType()));
-            assertTrue(permission.getConfig().containsValue(applyPolicies));
+            assertTrue(policyModel.getAssociatedPolicies().stream().map(Policy::getId).collect(Collectors.toList()).containsAll(Arrays.asList(associatedPolicies)));
+
             assertEquals(resourceServer.getId(), policyModel.getResourceServer().getId());
         });
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ScopeManagementTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ScopeManagementTest.java
index b2e1a42..644883f 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ScopeManagementTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/ScopeManagementTest.java
@@ -57,7 +57,7 @@ public class ScopeManagementTest extends AbstractPhotozAdminTest {
         ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId());
+            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
 
             assertNotNull(scopeModel);
             assertEquals(scope.getId(), scopeModel.getId());
@@ -86,7 +86,7 @@ public class ScopeManagementTest extends AbstractPhotozAdminTest {
         ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
 
         onAuthorizationSession(authorizationProvider -> {
-            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId());
+            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
 
             assertNotNull(scopeModel);
             assertEquals(scope.getId(), scopeModel.getId());
@@ -138,7 +138,7 @@ public class ScopeManagementTest extends AbstractPhotozAdminTest {
         assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
 
         onAuthorizationSession(authorizationProvider -> {
-            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId());
+            Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
 
             assertNull(scopeModel);
         });
diff --git a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
index 3f4ddd1..27e9f5e 100755
--- a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
@@ -64,7 +64,7 @@
 
     "connectionsJpa": {
         "default": {
-            "url": "${keycloak.connectionsJpa.url:jdbc:h2:mem:test}",
+            "url": "${keycloak.connectionsJpa.url:jdbc:h2:mem:test;DB_CLOSE_DELAY=-1}",
             "driver": "${keycloak.connectionsJpa.driver:org.h2.Driver}",
             "driverDialect": "${keycloak.connectionsJpa.driverDialect:}",
             "user": "${keycloak.connectionsJpa.user:sa}",
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/authorization/TestPolicyProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/authorization/TestPolicyProviderFactory.java
index 1fa5fc7..b3a0475 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/authorization/TestPolicyProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/authorization/TestPolicyProviderFactory.java
@@ -18,7 +18,6 @@ package org.keycloak.testsuite.authorization;
 
 import org.keycloak.Config;
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.evaluation.Evaluation;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
@@ -43,8 +42,8 @@ public class TestPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
-        return new TestPolicyProvider(policy, authorization);
+    public PolicyProvider create(AuthorizationProvider authorization) {
+        return new TestPolicyProvider(authorization);
     }
 
     @Override
@@ -79,11 +78,9 @@ public class TestPolicyProviderFactory implements PolicyProviderFactory {
 
     private class TestPolicyProvider implements PolicyProvider {
 
-        private final Policy policy;
         private final AuthorizationProvider authorization;
 
-        public TestPolicyProvider(Policy policy, AuthorizationProvider authorization) {
-            this.policy = policy;
+        public TestPolicyProvider(AuthorizationProvider authorization) {
             this.authorization = authorization;
         }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GenericPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GenericPolicyManagementTest.java
index e6f83d8..a1a2bfc 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GenericPolicyManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/GenericPolicyManagementTest.java
@@ -38,6 +38,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import static org.junit.Assert.assertEquals;
@@ -71,7 +72,7 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
         PolicyRepresentation newPolicy = createTestingPolicy().toRepresentation();
 
         assertEquals("Test Generic Policy", newPolicy.getName());
-        assertEquals("test", newPolicy.getType());
+        assertEquals("scope", newPolicy.getType());
         assertEquals(Logic.POSITIVE, newPolicy.getLogic());
         assertEquals(DecisionStrategy.UNANIMOUS, newPolicy.getDecisionStrategy());
         assertEquals("configuration for A", newPolicy.getConfig().get("configA"));
@@ -98,28 +99,28 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
     @Test
     public void testUpdate() {
         PolicyResource policyResource = createTestingPolicy();
-        PolicyRepresentation resource = policyResource.toRepresentation();
+        PolicyRepresentation policy = policyResource.toRepresentation();
 
-        resource.setName("changed");
-        resource.setLogic(Logic.NEGATIVE);
-        resource.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
-        resource.getConfig().put("configA", "changed configuration for A");
-        resource.getConfig().remove("configB");
-        resource.getConfig().put("configC", "changed configuration for C");
+        policy.setName("changed");
+        policy.setLogic(Logic.NEGATIVE);
+        policy.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
+        policy.getConfig().put("configA", "changed configuration for A");
+        policy.getConfig().remove("configB");
+        policy.getConfig().put("configC", "changed configuration for C");
 
-        policyResource.update(resource);
+        policyResource.update(policy);
 
-        resource = policyResource.toRepresentation();
+        policy = policyResource.toRepresentation();
 
-        assertEquals("changed", resource.getName());
-        assertEquals(Logic.NEGATIVE, resource.getLogic());
+        assertEquals("changed", policy.getName());
+        assertEquals(Logic.NEGATIVE, policy.getLogic());
 
-        assertEquals(DecisionStrategy.AFFIRMATIVE, resource.getDecisionStrategy());
-        assertEquals("changed configuration for A", resource.getConfig().get("configA"));
-        assertNull(resource.getConfig().get("configB"));
-        assertEquals("changed configuration for C", resource.getConfig().get("configC"));
+        assertEquals(DecisionStrategy.AFFIRMATIVE, policy.getDecisionStrategy());
+        assertEquals("changed configuration for A", policy.getConfig().get("configA"));
+        assertNull(policy.getConfig().get("configB"));
+        assertEquals("changed configuration for C", policy.getConfig().get("configC"));
 
-        Map<String, String> config = resource.getConfig();
+        Map<String, String> config = policy.getConfig();
 
         config.put("applyPolicies", buildConfigOption(findPolicyByName("Test Associated C").getId()));
 
@@ -127,22 +128,25 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
 
         config.put("scopes", buildConfigOption(findScopeByName("Test Scope A").getId()));
 
-        policyResource.update(resource);
+        policyResource.update(policy);
 
-        resource = policyResource.toRepresentation();
-        config = resource.getConfig();
+        policy = policyResource.toRepresentation();
+        config = policy.getConfig();
 
-        assertAssociatedPolicy("Test Associated C", resource);
-        assertFalse(config.get("applyPolicies").contains(findPolicyByName("Test Associated A").getId()));
-        assertFalse(config.get("applyPolicies").contains(findPolicyByName("Test Associated B").getId()));
+        assertAssociatedPolicy("Test Associated C", policy);
+        List<PolicyRepresentation> associatedPolicies = getClientResource().authorization().policies().policy(policy.getId()).associatedPolicies();
+        assertFalse(associatedPolicies.stream().filter(associated -> associated.getId().equals(findPolicyByName("Test Associated A").getId())).findFirst().isPresent());
+        assertFalse(associatedPolicies.stream().filter(associated -> associated.getId().equals(findPolicyByName("Test Associated B").getId())).findFirst().isPresent());
 
-        assertAssociatedResource("Test Resource B", resource);
-        assertFalse(config.get("resources").contains(findResourceByName("Test Resource A").getId()));
-        assertFalse(config.get("resources").contains(findResourceByName("Test Resource C").getId()));
+        assertAssociatedResource("Test Resource B", policy);
+        List<ResourceRepresentation> resources = policyResource.resources();
+        assertFalse(resources.contains(findResourceByName("Test Resource A")));
+        assertFalse(resources.contains(findResourceByName("Test Resource C")));
 
-        assertAssociatedScope("Test Scope A", resource);
-        assertFalse(config.get("scopes").contains(findScopeByName("Test Scope B").getId()));
-        assertFalse(config.get("scopes").contains(findScopeByName("Test Scope C").getId()));
+        assertAssociatedScope("Test Scope A", policy);
+        List<ScopeRepresentation> scopes = getClientResource().authorization().policies().policy(policy.getId()).scopes();
+        assertFalse(scopes.contains(findScopeByName("Test Scope B").getId()));
+        assertFalse(scopes.contains(findScopeByName("Test Scope C").getId()));
     }
 
     @Test
@@ -186,7 +190,7 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
         PolicyRepresentation newPolicy = new PolicyRepresentation();
 
         newPolicy.setName(name);
-        newPolicy.setType("test");
+        newPolicy.setType("scope");
         newPolicy.setConfig(config);
 
         PoliciesResource policies = getClientResource().authorization().policies();
@@ -264,27 +268,38 @@ public class GenericPolicyManagementTest extends AbstractAuthorizationTest {
 
     private void assertAssociatedPolicy(String associatedPolicyName, PolicyRepresentation dependentPolicy) {
         PolicyRepresentation associatedPolicy = findPolicyByName(associatedPolicyName);
+        PoliciesResource policies = getClientResource().authorization().policies();
+        associatedPolicy = policies.policy(associatedPolicy.getId()).toRepresentation();
         assertNotNull(associatedPolicy);
-        assertTrue(dependentPolicy.getConfig().get("applyPolicies").contains(associatedPolicy.getId()));
-        assertEquals(1, associatedPolicy.getDependentPolicies().size());
-        assertEquals(dependentPolicy.getId(), associatedPolicy.getDependentPolicies().get(0).getId());
+        PolicyRepresentation finalAssociatedPolicy = associatedPolicy;
+        PolicyResource policyResource = policies.policy(dependentPolicy.getId());
+        List<PolicyRepresentation> associatedPolicies = policyResource.associatedPolicies();
+        assertTrue(associatedPolicies.stream().filter(associated -> associated.getId().equals(finalAssociatedPolicy.getId())).findFirst().isPresent());
+        List<PolicyRepresentation> dependentPolicies = policies.policy(associatedPolicy.getId()).dependentPolicies();
+        assertEquals(1, dependentPolicies.size());
+        assertEquals(dependentPolicy.getId(), dependentPolicies.get(0).getId());
     }
 
     private void assertAssociatedResource(String resourceName, PolicyRepresentation policy) {
         ResourceRepresentation resource = findResourceByName(resourceName);
         assertNotNull(resource);
-        assertTrue(policy.getConfig().get("resources").contains(resource.getId()));
-        assertEquals(1, resource.getPolicies().size());
-        assertTrue(resource.getPolicies().stream().map(PolicyRepresentation::getId).collect(Collectors.toList())
+        List<ResourceRepresentation> resources = getClientResource().authorization().policies().policy(policy.getId()).resources();
+        assertTrue(resources.contains(resource));
+        List<PolicyRepresentation> policies = getClientResource().authorization().resources().resource(resource.getId()).permissions();
+        assertEquals(1, policies.size());
+        assertTrue(policies.stream().map(PolicyRepresentation::getId).collect(Collectors.toList())
                 .contains(policy.getId()));
     }
 
     private void assertAssociatedScope(String scopeName, PolicyRepresentation policy) {
         ScopeRepresentation scope =  findScopeByName(scopeName);
+        scope = getClientResource().authorization().scopes().scope(scope.getId()).toRepresentation();
         assertNotNull(scope);
-        assertTrue(policy.getConfig().get("scopes").contains(scope.getId()));
-        assertEquals(1, scope.getPolicies().size());
-        assertTrue(scope.getPolicies().stream().map(PolicyRepresentation::getId).collect(Collectors.toList())
+        List<ScopeRepresentation> scopes = getClientResource().authorization().policies().policy(policy.getId()).scopes();
+        assertTrue(scopes.stream().map((Function<ScopeRepresentation, String>) rep -> rep.getId()).collect(Collectors.toList()).contains(scope.getId()));
+        List<PolicyRepresentation> permissions = getClientResource().authorization().scopes().scope(scope.getId()).permissions();
+        assertEquals(1, permissions.size());
+        assertTrue(permissions.stream().map(PolicyRepresentation::getId).collect(Collectors.toList())
                 .contains(policy.getId()));
     }
 }
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 88dbfcd..5380f17 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -1036,6 +1036,10 @@ authz-result=Result
 authz-authorization-services-enabled=Authorization Enabled
 authz-authorization-services-enabled.tooltip=Enable/Disable fine-grained authorization support for a client
 authz-required=Required
+authz-show-details=Show Details
+authz-hide-details=Hide Details
+authz-associated-permissions=Associated Permissions
+authz-no-permission-associated=No permissions associated
 
 # Authz Settings
 authz-import-config.tooltip=Import a JSON file containing authorization settings for this resource server.
@@ -1056,6 +1060,7 @@ authz-export-settings.tooltip=Export and download all authorization settings for
 authz-no-resources-available=No resources available.
 authz-no-scopes-assigned=No scopes assigned.
 authz-no-type-defined=No type defined.
+authz-no-uri-defined=No URI defined.
 authz-no-permission-assigned=No permission assigned.
 authz-no-policy-assigned=No policy assigned.
 authz-create-permission=Create permission
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index ea039c1..2a86b93 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -86,10 +86,13 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route, 
     $scope.query = {
         realm: realm.realm,
         client : client.id,
+        deep: false,
         max : 20,
         first : 0
     };
 
+    $scope.listSizes = [5, 10, 20];
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
@@ -124,10 +127,49 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route, 
     $scope.searchQuery = function() {
         $scope.searchLoaded = false;
 
-        $scope.resources = ResourceServerResource.query($scope.query, function() {
+        ResourceServerResource.query($scope.query, function(response) {
             $scope.searchLoaded = true;
             $scope.lastSearch = $scope.query.search;
+            $scope.resources = response;
+            if ($scope.detailsFilter) {
+                $scope.showDetails();
+            }
+        });
+    };
+
+    $scope.loadDetails = function (resource) {
+        if (resource.details) {
+            resource.details.loaded = !resource.details.loaded;
+            return;
+        }
+
+        resource.details = {loaded: false};
+
+        ResourceServerResource.scopes({
+            realm : $route.current.params.realm,
+            client : client.id,
+            rsrid : resource._id
+        }, function(response) {
+            resource.scopes = response;
+            ResourceServerResource.permissions({
+                realm : $route.current.params.realm,
+                client : client.id,
+                rsrid : resource._id
+            }, function(response) {
+                resource.policies = response;
+                resource.details.loaded = true;
+            });
         });
+    }
+
+    $scope.showDetails = function(item) {
+        if (item) {
+            $scope.loadDetails(item);
+        } else {
+            for (i = 0; i < $scope.resources.length; i++) {
+                $scope.loadDetails($scope.resources[i]);
+            }
+        }
     };
 });
 
@@ -135,9 +177,36 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
     $scope.realm = realm;
     $scope.client = client;
 
-    ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-        $scope.scopes = data;
-    });
+    $scope.scopesUiSelect = {
+        minimumInputLength: 1,
+        delay: 500,
+        allowClear: true,
+        query: function (query) {
+            var data = {results: []};
+            if ('' == query.term.trim()) {
+                query.callback(data);
+                return;
+            }
+            $scope.query = {
+                realm: realm.realm,
+                client : client.id,
+                name: query.term.trim(),
+                deep: false,
+                max : 20,
+                first : 0
+            };
+            ResourceServerScope.query($scope.query, function(response) {
+                data.results = response;
+                query.callback(data);
+            });
+        },
+        formatResult: function(object, container, query) {
+            return object.name;
+        },
+        formatSelection: function(object, container, query) {
+            return object.name;
+        }
+    };
 
     var $instance = this;
 
@@ -165,6 +234,9 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
             }, true);
 
             $scope.save = function() {
+                for (i = 0; i < $scope.resource.scopes.length; i++) {
+                    delete $scope.resource.scopes[i].text;
+                }
                 $instance.checkNameAvailability(function () {
                     ResourceServerResource.save({realm : realm.realm, client : $scope.client.id}, $scope.resource, function(data) {
                         $location.url("/realms/" + realm.realm + "/clients/" + $scope.client.id + "/authz/resource-server/resource/" + data._id);
@@ -186,17 +258,9 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                     data.scopes = [];
                 }
 
-                if (!data.policies) {
-                    data.policies = [];
-                }
-
                 $scope.resource = angular.copy(data);
                 $scope.changed = false;
 
-                for (i = 0; i < $scope.resource.scopes.length; i++) {
-                    $scope.resource.scopes[i] = $scope.resource.scopes[i].name;
-                }
-
                 $scope.originalResource = angular.copy($scope.resource);
 
                 $scope.$watch('resource', function() {
@@ -206,6 +270,9 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                 }, true);
 
                 $scope.save = function() {
+                    for (i = 0; i < $scope.resource.scopes.length; i++) {
+                        delete $scope.resource.scopes[i].text;
+                    }
                     $instance.checkNameAvailability(function () {
                         ResourceServerResource.update({realm : realm.realm, client : $scope.client.id, rsrid : $scope.resource._id}, $scope.resource, function() {
                             $route.reload();
@@ -215,22 +282,28 @@ module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $r
                 }
 
                 $scope.remove = function() {
-                    var msg = "";
-
-                    if ($scope.resource.policies.length > 0) {
-                        msg = "<p>This resource is referenced in some policies:</p>";
-                        msg += "<ul>";
-                        for (i = 0; i < $scope.resource.policies.length; i++) {
-                            msg+= "<li><strong>" + $scope.resource.policies[i].name + "</strong></li>";
+                    ResourceServerResource.permissions({
+                        realm : $route.current.params.realm,
+                        client : client.id,
+                        rsrid : $scope.resource._id
+                    }, function (permissions) {
+                        var msg = "";
+
+                        if (permissions.length > 0 && !$scope.deleteConsent) {
+                            msg = "<p>This resource is referenced in some policies:</p>";
+                            msg += "<ul>";
+                            for (i = 0; i < permissions.length; i++) {
+                                msg+= "<li><strong>" + permissions[i].name + "</strong></li>";
+                            }
+                            msg += "</ul>";
+                            msg += "<p>If you remove this resource, the policies above will be affected and will not be associated with this resource anymore.</p>";
                         }
-                        msg += "</ul>";
-                        msg += "<p>If you remove this resource, the policies above will be affected and will not be associated with this resource anymore.</p>";
-                    }
 
-                    AuthzDialog.confirmDeleteWithMsg($scope.resource.name, "Resource", msg, function() {
-                        ResourceServerResource.delete({realm : realm.realm, client : $scope.client.id, rsrid : $scope.resource._id}, null, function() {
-                            $location.url("/realms/" + realm.realm + "/clients/" + $scope.client.id + "/authz/resource-server/resource");
-                            Notifications.success("The resource has been deleted.");
+                        AuthzDialog.confirmDeleteWithMsg($scope.resource.name, "Resource", msg, function() {
+                            ResourceServerResource.delete({realm : realm.realm, client : $scope.client.id, rsrid : $scope.resource._id}, null, function() {
+                                $location.url("/realms/" + realm.realm + "/clients/" + $scope.client.id + "/authz/resource-server/resource");
+                                Notifications.success("The resource has been deleted.");
+                            });
                         });
                     });
                 }
@@ -269,10 +342,13 @@ module.controller('ResourceServerScopeCtrl', function($scope, $http, $route, $lo
     $scope.query = {
         realm: realm.realm,
         client : client.id,
+        deep: false,
         max : 20,
         first : 0
     };
 
+    $scope.listSizes = [5, 10, 20];
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
@@ -304,14 +380,53 @@ module.controller('ResourceServerScopeCtrl', function($scope, $http, $route, $lo
         $scope.searchQuery();
     }
 
-    $scope.searchQuery = function() {
+    $scope.searchQuery = function(detailsFilter) {
         $scope.searchLoaded = false;
 
-        $scope.scopes = ResourceServerScope.query($scope.query, function() {
+        ResourceServerScope.query($scope.query, function(response) {
+            $scope.scopes = response;
             $scope.searchLoaded = true;
             $scope.lastSearch = $scope.query.search;
+            if ($scope.detailsFilter) {
+                $scope.showDetails();
+            }
         });
     };
+
+    $scope.loadDetails = function (scope) {
+        if (scope.details) {
+            scope.details.loaded = !scope.details.loaded;
+            return;
+        }
+
+        scope.details = {loaded: false};
+
+        ResourceServerScope.resources({
+            realm : $route.current.params.realm,
+            client : client.id,
+            id : scope.id
+        }, function(response) {
+            scope.resources = response;
+            ResourceServerScope.permissions({
+                realm : $route.current.params.realm,
+                client : client.id,
+                id : scope.id
+            }, function(response) {
+                scope.policies = response;
+                scope.details.loaded = true;
+            });
+        });
+    }
+
+    $scope.showDetails = function(item) {
+        if (item) {
+            $scope.loadDetails(item);
+        } else {
+            for (i = 0; i < $scope.scopes.length; i++) {
+                $scope.loadDetails($scope.scopes[i]);
+            }
+        }
+    };
 });
 
 module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $route, $location, realm, ResourceServer, client, ResourceServerScope, AuthzDialog, Notifications) {
@@ -377,22 +492,28 @@ module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $rout
                 }
 
                 $scope.remove = function() {
-                    var msg = "";
-
-                    if ($scope.scope.policies.length > 0) {
-                        msg = "<p>This resource is referenced in some policies:</p>";
-                        msg += "<ul>";
-                        for (i = 0; i < $scope.scope.policies.length; i++) {
-                            msg+= "<li><strong>" + $scope.scope.policies[i].name + "</strong></li>";
+                    ResourceServerScope.permissions({
+                        realm : $route.current.params.realm,
+                        client : client.id,
+                        id : $scope.scope.id
+                    }, function (permissions) {
+                        var msg = "";
+
+                        if (permissions.length > 0 && !$scope.deleteConsent) {
+                            msg = "<p>This scope is referenced in some policies:</p>";
+                            msg += "<ul>";
+                            for (i = 0; i < permissions.length; i++) {
+                                msg+= "<li><strong>" + permissions[i].name + "</strong></li>";
+                            }
+                            msg += "</ul>";
+                            msg += "<p>If you remove this scope, the policies above will be affected and will not be associated with this scope anymore.</p>";
                         }
-                        msg += "</ul>";
-                        msg += "<p>If you remove this resource, the policies above will be affected and will not be associated with this resource anymore.</p>";
-                    }
 
-                    AuthzDialog.confirmDeleteWithMsg($scope.scope.name, "Scope", msg, function() {
-                        ResourceServerScope.delete({realm : realm.realm, client : $scope.client.id, id : $scope.scope.id}, null, function() {
-                            $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/scope");
-                            Notifications.success("The scope has been deleted.");
+                        AuthzDialog.confirmDeleteWithMsg($scope.scope.name, "Scope", msg, function() {
+                            ResourceServerScope.delete({realm : realm.realm, client : $scope.client.id, id : $scope.scope.id}, null, function() {
+                                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/scope");
+                                Notifications.success("The scope has been deleted.");
+                            });
                         });
                     });
                 }
@@ -432,10 +553,12 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
         realm: realm.realm,
         client : client.id,
         permission: false,
-        max : 20,
+        max: 20,
         first : 0
     };
 
+    $scope.listSizes = [5, 10, 20];
+
     PolicyProvider.query({
         realm : $route.current.params.realm,
         client : client.id
@@ -481,17 +604,41 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
         $scope.searchLoaded = false;
 
         ResourceServerPolicy.query($scope.query, function(data) {
-            $scope.policies = [];
-
-            for (i = 0; i < data.length; i++) {
-                if (data[i].type != 'resource' && data[i].type != 'scope') {
-                    $scope.policies.push(data[i]);
-                }
-            }
-
+            $scope.policies = data;
             $scope.searchLoaded = true;
             $scope.lastSearch = $scope.query.search;
+            if ($scope.detailsFilter) {
+                $scope.showDetails();
+            }
+        });
+    };
+
+    $scope.loadDetails = function (policy) {
+        if (policy.details) {
+            policy.details.loaded = !policy.details.loaded;
+            return;
+        }
+
+        policy.details = {loaded: false};
+
+        ResourceServerPolicy.dependentPolicies({
+            realm : $route.current.params.realm,
+            client : client.id,
+            id : policy.id
+        }, function(response) {
+            policy.dependentPolicies = response;
+            policy.details.loaded = true;
         });
+    }
+
+    $scope.showDetails = function(item) {
+        if (item) {
+            $scope.loadDetails(item);
+        } else {
+            for (i = 0; i < $scope.policies.length; i++) {
+                $scope.loadDetails($scope.policies[i]);
+            }
+        }
     };
 });
 
@@ -508,6 +655,8 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
         first : 0
     };
 
+    $scope.listSizes = [5, 10, 20];
+
     PolicyProvider.query({
         realm : $route.current.params.realm,
         client : client.id
@@ -553,18 +702,42 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
         $scope.searchLoaded = false;
 
         ResourceServerPolicy.query($scope.query, function(data) {
-            $scope.policies = [];
-
-            for (i = 0; i < data.length; i++) {
-                if (data[i].type == 'resource' || data[i].type == 'scope') {
-                    $scope.policies.push(data[i]);
-                }
-            }
-
+            $scope.policies = data;
             $scope.searchLoaded = true;
             $scope.lastSearch = $scope.query.search;
+            if ($scope.detailsFilter) {
+                $scope.showDetails();
+            }
         });
     };
+
+    $scope.loadDetails = function (policy) {
+        if (policy.details) {
+            policy.details.loaded = !policy.details.loaded;
+            return;
+        }
+
+        policy.details = {loaded: false};
+
+        ResourceServerPolicy.associatedPolicies({
+            realm : $route.current.params.realm,
+            client : client.id,
+            id : policy.id
+        }, function(response) {
+            policy.associatedPolicies = response;
+            policy.details.loaded = true;
+        });
+    }
+
+    $scope.showDetails = function(item) {
+        if (item) {
+            $scope.loadDetails(item);
+        } else {
+            for (i = 0; i < $scope.policies.length; i++) {
+                $scope.loadDetails($scope.policies[i]);
+            }
+        }
+    };
 });
 
 module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http, $route, realm, client, PolicyController) {
@@ -623,19 +796,64 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
         },
 
         onInit : function() {
-            ResourceServerResource.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.resources = data;
-            });
-
-            ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.policies = [];
+            $scope.resourcesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                id: function(resource){ return resource._id; },
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
+                    }
+                    $scope.query = {
+                        realm: realm.realm,
+                        client : client.id,
+                        name: query.term.trim(),
+                        deep: false,
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerResource.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
+                    });
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
+                }
+            };
 
-                for (i = 0; i < data.length; i++) {
-                    if (data[i].type != 'resource' && data[i].type != 'scope') {
-                        $scope.policies.push(data[i]);
+            $scope.policiesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
                     }
+                    $scope.query = {
+                        realm: realm.realm,
+                        client : client.id,
+                        permission: false,
+                        name: query.term.trim(),
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerPolicy.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
+                    });
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
                 }
-            });
+            };
 
             $scope.applyToResourceType = function() {
                 if ($scope.policy.config.default) {
@@ -648,30 +866,69 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
 
         onInitUpdate : function(policy) {
             policy.config.default = eval(policy.config.default);
-            policy.config.resources = eval(policy.config.resources);
-            policy.config.applyPolicies = eval(policy.config.applyPolicies);
+            policy.config.resources = {};
+            ResourceServerPolicy.resources({
+                realm : $route.current.params.realm,
+                client : client.id,
+                id : policy.id
+            }, function(resources) {
+                resources[0].text = resources[0].name;
+                $scope.policy.config.resources = resources[0];
+            });
+
+            policy.config.applyPolicies = [];
+            ResourceServerPolicy.associatedPolicies({
+                realm : $route.current.params.realm,
+                client : client.id,
+                id : policy.id
+            }, function(policies) {
+                for (i = 0; i < policies.length; i++) {
+                    policies[i].text = policies[i].name;
+                    $scope.policy.config.applyPolicies.push(policies[i]);
+                }
+            });
         },
 
         onUpdate : function() {
-            $scope.policy.config.resources = JSON.stringify($scope.policy.config.resources);
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+            $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
+            }
+
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         },
 
         onInitCreate : function(newPolicy) {
             newPolicy.decisionStrategy = 'UNANIMOUS';
             newPolicy.config = {};
-            newPolicy.config.resources = '';
+            newPolicy.config.resources = null;
 
             var resourceId = $location.search()['rsrid'];
 
             if (resourceId) {
-                newPolicy.config.resources = [resourceId];
+                ResourceServerResource.get({
+                    realm : $route.current.params.realm,
+                    client : client.id,
+                    rsrid : resourceId
+                }, function(data) {
+                    data.text = data.name;
+                    $scope.policy.config.resources = data;
+                });
             }
         },
 
         onCreate : function() {
-            $scope.policy.config.resources = JSON.stringify($scope.policy.config.resources);
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+            $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
+            }
+
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         }
     }, realm, client, $scope);
 });
@@ -687,105 +944,241 @@ module.controller('ResourceServerPolicyScopeDetailCtrl', function($scope, $route
         },
 
         onInit : function() {
-            ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.scopes = data;
-            });
-
-            ResourceServerResource.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.resources = data;
-            });
-
-            ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.policies = [];
-
-                for (i = 0; i < data.length; i++) {
-                    if (data[i].type != 'resource' && data[i].type != 'scope') {
-                        $scope.policies.push(data[i]);
+            $scope.scopesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
                     }
+                    $scope.query = {
+                        realm: realm.realm,
+                        client : client.id,
+                        name: query.term.trim(),
+                        deep: false,
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerScope.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
+                    });
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
                 }
-            });
-
-            $scope.resolveScopes = function(policy, keepScopes) {
-                if (!keepScopes) {
-                    policy.config.scopes = [];
-                }
+            };
 
-                if (!policy) {
-                    policy = $scope.policy;
+            $scope.resourcesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                id: function(resource){ return resource._id; },
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
+                    }
+                    $scope.query = {
+                        realm: realm.realm,
+                        client : client.id,
+                        name: query.term.trim(),
+                        deep: false,
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerResource.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
+                    });
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
                 }
+            };
 
-                if (policy.config.resources != null) {
-                    ResourceServerResource.get({
-                        realm : $route.current.params.realm,
+            $scope.policiesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
+                    }
+                    $scope.query = {
+                        realm: realm.realm,
                         client : client.id,
-                        rsrid : policy.config.resources
-                    }, function(data) {
-                        $scope.scopes = data.scopes;
+                        permission: false,
+                        name: query.term.trim(),
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerPolicy.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
                     });
-                } else {
-                    ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-                        $scope.scopes = data;
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
+                }
+            };
+
+            $scope.selectResource = function() {
+                if ($scope.policy.config.resources) {
+                    ResourceServerResource.scopes({
+                        realm: $route.current.params.realm,
+                        client: client.id,
+                        rsrid: $scope.policy.config.resources._id
+                    }, function (data) {
+                        $scope.policy.config.resources.scopes = data;
                     });
                 }
             }
         },
 
         onInitUpdate : function(policy) {
-            if (policy.config.resources) {
-                policy.config.resources = eval(policy.config.resources);
+            policy.config.resources = eval(policy.config.resources);
 
-                if (policy.config.resources.length > 0) {
-                    policy.config.resources = policy.config.resources[0];
-                } else {
-                    policy.config.resources = null;
-                }
+            if (policy.config.resources == null) {
+                policy.config.resources = [];
             }
 
-            $scope.resolveScopes(policy, true);
+            if (policy.config.resources.length > 0) {
+                ResourceServerResource.query({
+                    realm: $route.current.params.realm,
+                    client: client.id,
+                    _id: policy.config.resources[0],
+                    deep: false
+                }, function (data) {
+                    data[0].text = data[0].name;
+                    $scope.policy.config.resources = data[0];
+                    ResourceServerResource.scopes({
+                        realm: $route.current.params.realm,
+                        client: client.id,
+                        rsrid: policy.config.resources[0]
+                    }, function (data) {
+                        $scope.policy.config.resources.scopes = data;
+                    });
+                    ResourceServerPolicy.scopes({
+                        realm : $route.current.params.realm,
+                        client : client.id,
+                        id : policy.id
+                    }, function(scopes) {
+                        $scope.policy.config.scopes = [];
+                        for (i = 0; i < scopes.length; i++) {
+                            $scope.policy.config.scopes.push(scopes[i].id);
+                        }
+                    });
+                });
+            } else {
+                policy.config.resources = null;
+                ResourceServerPolicy.scopes({
+                    realm : $route.current.params.realm,
+                    client : client.id,
+                    id : policy.id
+                }, function(scopes) {
+                    $scope.policy.config.scopes = [];
+                    for (i = 0; i < scopes.length; i++) {
+                        scopes[i].text = scopes[i].name;
+                        $scope.policy.config.scopes.push(scopes[i]);
+                    }
+                });
+            }
 
-            policy.config.applyPolicies = eval(policy.config.applyPolicies);
-            policy.config.scopes = eval(policy.config.scopes);
+            policy.config.applyPolicies = [];
+            ResourceServerPolicy.associatedPolicies({
+                realm : $route.current.params.realm,
+                client : client.id,
+                id : policy.id
+            }, function(policies) {
+                for (i = 0; i < policies.length; i++) {
+                    policies[i].text = policies[i].name;
+                    $scope.policy.config.applyPolicies.push(policies[i]);
+                }
+            });
         },
 
         onUpdate : function() {
             if ($scope.policy.config.resources != null) {
-                var resources = undefined;
+                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            }
 
-                if ($scope.policy.config.resources.length != 0) {
-                    resources = JSON.stringify([$scope.policy.config.resources])
+            var scopes = [];
+
+            for (i = 0; i < $scope.policy.config.scopes.length; i++) {
+                if ($scope.policy.config.resources == null) {
+                    scopes.push($scope.policy.config.scopes[i].id);
+                } else {
+                    scopes.push($scope.policy.config.scopes[i]);
                 }
+            }
 
-                $scope.policy.config.resources = resources;
+            $scope.policy.config.scopes = JSON.stringify(scopes);
+
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
             }
 
-            $scope.policy.config.scopes = JSON.stringify($scope.policy.config.scopes);
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         },
 
         onInitCreate : function(newPolicy) {
             newPolicy.decisionStrategy = 'UNANIMOUS';
             newPolicy.config = {};
-            newPolicy.config.resources = '';
+            newPolicy.config.resources = null;
 
             var scopeId = $location.search()['scpid'];
 
             if (scopeId) {
-                newPolicy.config.scopes = [scopeId];
+                ResourceServerScope.get({
+                    realm: $route.current.params.realm,
+                    client: client.id,
+                    id: scopeId,
+                }, function (data) {
+                    data.text = data.name;
+                    if (!$scope.policy.config.scopes) {
+                        $scope.policy.config.scopes = [];
+                    }
+                    $scope.policy.config.scopes.push(data);
+                });
             }
         },
 
         onCreate : function() {
             if ($scope.policy.config.resources != null) {
-                var resources = undefined;
+                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            }
+
+            var scopes = [];
 
-                if ($scope.policy.config.resources.length != 0) {
-                    resources = JSON.stringify([$scope.policy.config.resources])
+            for (i = 0; i < $scope.policy.config.scopes.length; i++) {
+                if ($scope.policy.config.scopes[i].id) {
+                    scopes.push($scope.policy.config.scopes[i].id);
+                } else {
+                    scopes.push($scope.policy.config.scopes[i]);
                 }
+            }
+
+            $scope.policy.config.scopes = JSON.stringify(scopes);
 
-                $scope.policy.config.resources = resources;
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
             }
-            $scope.policy.config.scopes = JSON.stringify($scope.policy.config.scopes);
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         }
     }, realm, client, $scope);
 });
@@ -1250,23 +1643,58 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
         },
 
         onInit : function() {
-            ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.policies = [];
-
-                for (i = 0; i < data.length; i++) {
-                    if (data[i].type != 'resource' && data[i].type != 'scope') {
-                        $scope.policies.push(data[i]);
+            $scope.policiesUiSelect = {
+                minimumInputLength: 1,
+                delay: 500,
+                allowClear: true,
+                query: function (query) {
+                    var data = {results: []};
+                    if ('' == query.term.trim()) {
+                        query.callback(data);
+                        return;
                     }
+                    $scope.query = {
+                        realm: realm.realm,
+                        client : client.id,
+                        permission: false,
+                        name: query.term.trim(),
+                        max : 20,
+                        first : 0
+                    };
+                    ResourceServerPolicy.query($scope.query, function(response) {
+                        data.results = response;
+                        query.callback(data);
+                    });
+                },
+                formatResult: function(object, container, query) {
+                    object.text = object.name;
+                    return object.name;
                 }
-            });
+            };
         },
 
         onInitUpdate : function(policy) {
-            policy.config.applyPolicies = eval(policy.config.applyPolicies);
+            policy.config.applyPolicies = [];
+            ResourceServerPolicy.associatedPolicies({
+                realm : $route.current.params.realm,
+                client : client.id,
+                id : policy.id
+            }, function(policies) {
+                for (i = 0; i < policies.length; i++) {
+                    policies[i].text = policies[i].name;
+                    $scope.policy.config.applyPolicies.push(policies[i]);
+                }
+            });
         },
 
         onUpdate : function() {
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
+            }
+
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         },
 
         onInitCreate : function(newPolicy) {
@@ -1275,7 +1703,13 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
         },
 
         onCreate : function() {
-            $scope.policy.config.applyPolicies = JSON.stringify($scope.policy.config.applyPolicies);
+            var policies = [];
+
+            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
+                policies.push($scope.policy.config.applyPolicies[i].id);
+            }
+
+            $scope.policy.config.applyPolicies = JSON.stringify(policies);
         }
     }, realm, client, $scope);
 });
@@ -1357,9 +1791,9 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                 }
             } else {
                 ResourceServerPolicy.get({
-                    realm : $route.current.params.realm,
+                    realm: realm.realm,
                     client : client.id,
-                    id : $route.current.params.id,
+                    id: $route.current.params.id
                 }, function(data) {
                     $scope.originalPolicy = data;
                     var policy = angular.copy(data);
@@ -1408,25 +1842,31 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                 $scope.remove = function() {
                     var msg = "";
 
-                    if ($scope.policy.dependentPolicies.length > 0) {
-                        msg = "<p>This policy is being used by other policies:</p>";
-                        msg += "<ul>";
-                        for (i = 0; i < $scope.policy.dependentPolicies.length; i++) {
-                            msg+= "<li><strong>" + $scope.policy.dependentPolicies[i].name + "</strong></li>";
+                    ResourceServerPolicy.dependentPolicies({
+                        realm : $route.current.params.realm,
+                        client : client.id,
+                        id : $scope.policy.id
+                    }, function (dependentPolicies) {
+                        if (dependentPolicies.length > 0 && !$scope.deleteConsent) {
+                            msg = "<p>This policy is being used by other policies:</p>";
+                            msg += "<ul>";
+                            for (i = 0; i < dependentPolicies.length; i++) {
+                                msg+= "<li><strong>" + dependentPolicies[i].name + "</strong></li>";
+                            }
+                            msg += "</ul>";
+                            msg += "<p>If you remove this policy, the policies above will be affected and will not be associated with this policy anymore.</p>";
                         }
-                        msg += "</ul>";
-                        msg += "<p>If you remove this policy, the policies above will be affected and will not be associated with this policy anymore.</p>";
-                    }
 
-                    AuthzDialog.confirmDeleteWithMsg($scope.policy.name, "Policy", msg, function() {
-                        ResourceServerPolicy.delete({realm : $scope.realm.realm, client : $scope.client.id, id : $scope.policy.id}, null, function() {
-                            if (delegate.isPermission()) {
-                                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission");
-                                Notifications.success("The permission has been deleted.");
-                            } else {
-                                $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy");
-                                Notifications.success("The policy has been deleted.");
-                            }
+                        AuthzDialog.confirmDeleteWithMsg($scope.policy.name, "Policy", msg, function() {
+                            ResourceServerPolicy.delete({realm : $scope.realm.realm, client : $scope.client.id, id : $scope.policy.id}, null, function() {
+                                if (delegate.isPermission()) {
+                                    $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission");
+                                    Notifications.success("The permission has been deleted.");
+                                } else {
+                                    $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy");
+                                    Notifications.success("The policy has been deleted.");
+                                }
+                            });
                         });
                     });
                 }
@@ -1465,13 +1905,8 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
     $scope.authzRequest.context = {};
     $scope.authzRequest.context.attributes = {};
     $scope.authzRequest.roleIds = [];
-    $scope.newResource = {};
     $scope.resultUrl = resourceUrl + '/partials/authz/policy/resource-server-policy-evaluate-result.html';
 
-    ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-        $scope.scopes = data;
-    });
-
     $scope.addContextAttribute = function() {
         if (!$scope.newContextAttribute.value || $scope.newContextAttribute.value == '') {
             Notifications.error("You must provide a value to a context attribute.");
@@ -1573,33 +2008,39 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
     }
 
     $scope.setApplyToResourceType = function() {
-        if ($scope.applyResourceType) {
-            ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-                $scope.scopes = data;
-            });
-        }
-
         delete $scope.newResource;
         $scope.authzRequest.resources = [];
     }
 
     $scope.addResource = function() {
-        var resource = {};
+        var resource = angular.copy($scope.newResource);
+
+        if (!resource) {
+            resource = {};
+        }
+
+        delete resource.text;
+
+        if (!$scope.newScopes || (resource._id != null && $scope.newScopes.length > 0 && $scope.newScopes[0].id)) {
+            $scope.newScopes = [];
+        }
 
-        resource.id = $scope.newResource._id;
+        var scopes = [];
 
-        for (i = 0; i < $scope.resources.length; i++) {
-            if ($scope.resources[i]._id == resource.id) {
-                resource.name = $scope.resources[i].name;
-                break;
+        for (i = 0; i < $scope.newScopes.length; i++) {
+            if ($scope.newScopes[i].name) {
+                scopes.push($scope.newScopes[i].name);
+            } else {
+                scopes.push($scope.newScopes[i]);
             }
         }
 
-        resource.scopes = $scope.newResource.scopes;
+        resource.scopes = scopes;
 
         $scope.authzRequest.resources.push(resource);
 
         delete $scope.newResource;
+        delete $scope.newScopes;
     }
 
     $scope.removeResource = function(index) {
@@ -1610,20 +2051,11 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
         if ($scope.newResource._id) {
             $scope.newResource.scopes = [];
             $scope.scopes = [];
-            ResourceServerResource.get({
+            ResourceServerResource.scopes({
                 realm: $route.current.params.realm,
-                client : client.id,
+                client: client.id,
                 rsrid: $scope.newResource._id
             }, function (data) {
-                $scope.scopes = data.scopes;
-                if (data.typedScopes) {
-                    for (i=0;i<data.typedScopes.length;i++) {
-                        $scope.scopes.push(data.typedScopes[i]);
-                    }
-                }
-            });
-        } else {
-            ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
                 $scope.scopes = data;
             });
         }
@@ -1647,7 +2079,17 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
             if (!$scope.newResource) {
                 $scope.newResource = {};
             }
-            $scope.authzRequest.resources[0].scopes = $scope.newResource.scopes;
+            if (!$scope.newScopes || ($scope.newResource._id != null && $scope.newScopes.length > 0 && $scope.newScopes[0].id)) {
+                $scope.newScopes = [];
+            }
+
+            var scopes = angular.copy($scope.newScopes);
+
+            for (i = 0; i < scopes.length; i++) {
+                delete scopes[i].text;
+            }
+
+            $scope.authzRequest.resources[0].scopes = scopes;
         }
 
         $http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/evaluate'
@@ -1697,9 +2139,64 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
         }
     };
 
-    ResourceServerResource.query({realm : realm.realm, client : client.id}, function (data) {
-        $scope.resources = data;
-    });
+    $scope.resourcesUiSelect = {
+        minimumInputLength: 1,
+        delay: 500,
+        allowClear: true,
+        id: function(resource){ return resource._id; },
+        query: function (query) {
+            var data = {results: []};
+            if ('' == query.term.trim()) {
+                query.callback(data);
+                return;
+            }
+            $scope.query = {
+                realm: realm.realm,
+                client : client.id,
+                name: query.term.trim(),
+                deep: false,
+                max : 20,
+                first : 0
+            };
+            ResourceServerResource.query($scope.query, function(response) {
+                data.results = response;
+                query.callback(data);
+            });
+        },
+        formatResult: function(object, container, query) {
+            object.text = object.name;
+            return object.name;
+        }
+    };
+
+    $scope.scopesUiSelect = {
+        minimumInputLength: 1,
+        delay: 500,
+        allowClear: true,
+        query: function (query) {
+            var data = {results: []};
+            if ('' == query.term.trim()) {
+                query.callback(data);
+                return;
+            }
+            $scope.query = {
+                realm: realm.realm,
+                client : client.id,
+                name: query.term.trim(),
+                deep: false,
+                max : 20,
+                first : 0
+            };
+            ResourceServerScope.query($scope.query, function(response) {
+                data.results = response;
+                query.callback(data);
+            });
+        },
+        formatResult: function(object, container, query) {
+            object.text = object.name;
+            return object.name;
+        }
+    };
 
     ResourceServer.get({
         realm : $route.current.params.realm,
@@ -1717,5 +2214,4 @@ module.controller('PolicyEvaluateCtrl', function($scope, $http, $route, $locatio
 
         $scope.authzRequest.userId = user.id;
     }
-
 });
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
index 795cf1d..1c4f584 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-services.js
@@ -16,7 +16,9 @@ module.factory('ResourceServerResource', function($resource) {
         rsrid : '@rsrid'
     }, {
         'update' : {method : 'PUT'},
-        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/resource/search', method : 'GET'}
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/resource/search', method : 'GET'},
+        'scopes' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/resource/:rsrid/scopes', method : 'GET', isArray: true},
+        'permissions' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/resource/:rsrid/permissions', method : 'GET', isArray: true}
     });
 });
 
@@ -27,7 +29,9 @@ module.factory('ResourceServerScope', function($resource) {
         id : '@id'
     }, {
         'update' : {method : 'PUT'},
-        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/scope/search', method : 'GET'}
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/scope/search', method : 'GET'},
+        'resources' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/scope/:id/resources', method : 'GET', isArray: true},
+        'permissions' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/scope/:id/permissions', method : 'GET', isArray: true},
     });
 });
 
@@ -38,7 +42,11 @@ module.factory('ResourceServerPolicy', function($resource) {
         id : '@id'
     }, {
         'update' : {method : 'PUT'},
-        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/search', method : 'GET'}
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/search', method : 'GET'},
+        'associatedPolicies' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:id/associatedPolicies', method : 'GET', isArray: true},
+        'dependentPolicies' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:id/dependentPolicies', method : 'GET', isArray: true},
+        'scopes' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:id/scopes', method : 'GET', isArray: true},
+        'resources' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:id/resources', method : 'GET', isArray: true}
     });
 });
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
index a8d4512..10e3170 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-resource-detail.html
@@ -39,9 +39,7 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resources' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2="{ minimumInputLength: 1}" id="reqActions" data-ng-model="policy.config.resources" data-placeholder="{{:: 'authz-select-resource' | translate}}..." multiple data-ng-required="!policy.config.default">
-                        <option ng-repeat="resource in resources" value="{{resource._id}}" ng-selected="true">{{resource.name}}</option>
-                    </select>
+                    <input type="hidden" ui-select2="resourcesUiSelect" id="reqActions" data-ng-model="policy.config.resources" data-placeholder="{{:: 'authz-select-resource' | translate}}..." data-ng-required="!policy.config.default"/>
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-resource-resource.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -58,9 +56,7 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2 id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required>
-                        <option ng-repeat="policy in policies" value="{{policy.id}}" ng-selected="true">{{policy.name}}</option>
-                    </select>
+                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
                 </div>
 
                 <kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
index 3d1660b..90a3dc6 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/provider/resource-server-policy-scope-detail.html
@@ -32,12 +32,7 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resource' | translate}}</label>
 
                 <div class="col-md-6">
-                    <select class="form-control" id="reqActions"
-                            ng-model="policy.config.resources"
-                            ng-change="resolveScopes(policy)"
-                            data-ng-options="resource._id as resource.name for resource in resources">
-                        <option value="">{{:: 'authz-any-resource' | translate}}...</option>
-                    </select>
+                    <input type="hidden" ui-select2="resourcesUiSelect" data-ng-change="selectResource()" id="reqActions" data-ng-model="policy.config.resources" data-placeholder="{{:: 'authz-any-resource' | translate}}..." />
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-scope-resource.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -45,25 +40,19 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2 id="reqActions"
+                    <select ui-select2 id="reqActions2"
                             data-ng-model="policy.config.scopes"
                             data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple
-                            data-ng-required="policy.config.resources != ''"
-                            data-ng-options="scope.id as scope.name for scope in scopes track by scope.id"/>
+                            data-ng-required="policy.config.resources != null"
+                            data-ng-options="scope.id as scope.name for scope in policy.config.resources.scopes track by scope.id"/>
                 </div>
-
                 <kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group clearfix" data-ng-show="!policy.config.resources">
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2="{ minimumInputLength: 1}" id="reqActions"
-                            data-ng-model="policy.config.scopes"
-                            data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple
-                            data-ng-required="policy.config.resources == ''"
-                            data-ng-options="scope.id as scope.name for scope in scopes track by scope.id"/>
-                    </select>
+                    <input type="hidden" ui-select2="scopesUiSelect" id="reqActions" data-ng-model="policy.config.scopes" data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple data-ng-required="policy.config.resources == null" />
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -71,9 +60,7 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2 id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required>
-                        <option ng-repeat="policy in policies" value="{{policy.id}}" ng-selected="true">{{policy.name}}</option>
-                    </select>
+                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
                 </div>
 
                 <kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
@@ -95,7 +82,6 @@
             </div>
             <input type="hidden" data-ng-model="policy.type"/>
         </fieldset>
-
         <div class="form-group" data-ng-show="access.manageAuthorization">
             <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
index bfd1b22..419622f 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
@@ -28,6 +28,12 @@
                                 </select>
                             </div>
                         </div>
+                        <div class="input-group">
+                            <select class="form-control search" data-ng-model="detailsFilter" data-ng-change="searchQuery();">
+                                <option value="" selected>Hide Details</option>
+                                <option value="true">Show Details</option>
+                            </select>
+                        </div>
                         <div class="pull-right">
                             <select class="form-control" ng-model="policyType"
                                     ng-options="p.name for p in policyProviders track by p.type"
@@ -42,7 +48,7 @@
                 <th>{{:: 'name' | translate}}</th>
                 <th>{{:: 'description' | translate}}</th>
                 <th>{{:: 'type' | translate}}</th>
-                <th>{{:: 'authz-associated-policies' | translate}}</th>
+                <th>{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
         <tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
@@ -52,22 +58,48 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
+                    <select class="first" data-ng-model="query.max"
+                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
+                    </select>
                 </div>
             </td>
         </tr>
         </tfoot>
         <tbody>
-            <tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
+            <tr ng-repeat-start="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
                 <td>{{policy.description}}</td>
                 <td>{{policy.type}}</td>
-                <td>
-                    <span data-ng-show="!policy.associatedPolicies.length">{{:: 'authz-no-policy-assigned' | translate}}</span>
-                    <span data-ng-show="policy.associatedPolicies.length > 0">
-                        <span ng-repeat="policy in policy.associatedPolicies">
-                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy/{{policy.type}}/{{policy.id}}">{{policy.name}}</a>{{$last ? '' : ', '}}
-                        </span>
-                    </span>
+                <td ng-if="!policy.details.loaded" class="kc-action-cell" data-ng-click="showDetails(policy);">
+                    {{:: 'authz-show-details' | translate}}
+                </td>
+                <td ng-if="policy.details.loaded" class="kc-action-cell" data-ng-click="showDetails(policy);">
+                    {{:: 'authz-hide-details' | translate}}
+                </td>
+            </tr>
+            <tr ng-if="policy.details && policy.details.loaded" ng-repeat-end="">
+                <td colspan="4">
+                    <div id="details">
+                        <table class="table kc-authz-table-expanded table-striped">
+                            <thead>
+                            <tr>
+                                <th>Associated Permissions</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>
+                                    <span data-ng-show="policy.associatedPolicies && !policy.associatedPolicies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
+                                    <ul ng-repeat="dep in policy.associatedPolicies" data-ng-show="policy.associatedPolicies.length > 0">
+                                        <li>
+                                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy/{{dep.type}}/{{dep.id}}">{{dep.name}}</a>
+                                        </li>
+                                    </ul>
+                                </td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
                 </td>
             </tr>
             <tr data-ng-show="(policies | filter:search).length == 0">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
index 7888f21..2544d3c 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-aggregate-detail.html
@@ -34,11 +34,8 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-policy-apply-policy' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <select ui-select2 id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required>
-                        <option ng-repeat="policy in policies" value="{{policy.id}}" ng-selected="true">{{policy.name}}</option>
-                    </select>
+                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
                 </div>
-
                 <kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group clearfix">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-evaluate.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-evaluate.html
index d884150..dbaedd3 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-evaluate.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-evaluate.html
@@ -172,14 +172,7 @@
                         <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resources' | translate}} <span class="required">*</span></label>
 
                         <div class="col-md-6">
-                            <select ui-select2="{ minimumInputLength: 1, allowClear:true }"
-                                    ng-model="newResource._id"
-                                    data-placeholder="Select a resource..."
-                                    data-ng-required="!applyResourceType && authzRequest.resources.length == 0 && !authzRequest.entitlements"
-                                    data-ng-click="resolveScopes()"
-                                    ng-options="resource._id as resource.name for resource in resources track by resource._id">
-                                <option value=""></option>
-                            </select>
+                            <input type="hidden" ui-select2="resourcesUiSelect" id="reqActions3" data-ng-change="resolveScopes()" data-ng-model="newResource" data-placeholder="{{:: 'authz-select-resource' | translate}}..." data-ng-required="!applyResourceType && authzRequest.resources.length == 0 && !authzRequest.entitlements" />
                         </div>
                         <kc-tooltip>{{:: 'authz-permission-resource-resource.tooltip' | translate}}</kc-tooltip>
                     </div>
@@ -199,12 +192,7 @@
                         <label class="col-md-2 control-label" for="newResource.scopes">{{:: 'authz-scopes' | translate}}</label>
 
                         <div class="col-md-6">
-                            <select ui-select2="{ minimumInputLength: 1}"
-                                    id="newResource.scopes"
-                                    multiple
-                                    data-ng-model="newResource.scopes"
-                                    data-placeholder="{{:: 'authz-select-scope' | translate}}..."
-                                    data-ng-options="scope.name as scope.name for scope in scopes track by scope.name"/>
+                            <input type="hidden" ui-select2="scopesUiSelect" id="reqActions" data-ng-model="newScopes" data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple />
                         </div>
 
                         <kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
@@ -215,7 +203,7 @@
                         <div class="col-md-6">
                             <select ui-select2
                                     id="newResource.scopes"
-                                    data-ng-model="newResource.scopes"
+                                    data-ng-model="newScopes"
                                     data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple>
                                 <option ng-repeat="scope in scopes" value="{{scope.name}}">{{scope.name}}</option>
                             </select>
@@ -246,11 +234,11 @@
                                         <td>{{resource.name ? resource.name : 'authz-evaluation-any-resource-with-scopes' | translate}}</td>
                                         <td>
                                             <span data-ng-show="!resource.scopes.length">{{:: 'authz-any-scope' | translate}}.</span>
-                                        <span data-ng-show="resource.scopes.length > 0">
-                                            <span ng-repeat="scope in resource.scopes">
-                                                {{scope}} {{$last ? '' : ', '}}
+                                            <span data-ng-show="resource.scopes.length > 0">
+                                                <span ng-repeat="scope in resource.scopes">
+                                                    {{scope.name ? scope.name : scope}} {{$last ? '' : ', '}}
+                                                </span>
                                             </span>
-                                        </span>
                                         </td>
                                         <td class="kc-action-cell">
                                             <button class="btn btn-default btn-block btn-sm"
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
index 2574f2d..9ad378a 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
@@ -27,8 +27,16 @@
                                     <option value="" selected ng-click="query.type = ''">{{:: 'authz-all-types' | translate}}</option>
                                 </select>
                             </div>
+                            <div class="input-group">
+                                <select class="form-control search" data-ng-model="detailsFilter" data-ng-change="searchQuery();">
+                                    <option value="" selected>Hide Details</option>
+                                    <option value="true">Show Details</option>
+                                </select>
+                            </div>
                         </div>
                         <div class="pull-right">
+                            <a id="hideDetails" data-ng-show="showDetailsFlag" class="btn btn-default" data-ng-click="showDetailsFlag = !showDetailsFlag;showDetails();" href="">{{:: 'authz-hide-details' | translate}}</a>
+                            <a id="showDetails" data-ng-hide="showDetailsFlag" class="btn btn-default" data-ng-click="showDetailsFlag = !showDetailsFlag;showDetails();" href="">{{:: 'authz-show-details' | translate}}</a>
                             <select class="form-control" ng-model="policyType"
                                     ng-options="p.name for p in policyProviders track by p.type"
                                     data-ng-change="addPolicy(policyType);">
@@ -42,6 +50,7 @@
                 <th>{{:: 'name' | translate}}</th>
                 <th>{{:: 'description' | translate}}</th>
                 <th>{{:: 'type' | translate}}</th>
+                <th>{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
         <tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
@@ -51,15 +60,49 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
+                    <select class="first" data-ng-model="query.max"
+                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
+                    </select>
                 </div>
             </td>
         </tr>
         </tfoot>
         <tbody>
-            <tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
+            <tr ng-repeat-start="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
                 <td>{{policy.description}}</td>
                 <td>{{policy.type}}</td>
+                <td ng-if="!policy.details.loaded" class="kc-action-cell" data-ng-click="showDetails(policy);">
+                    {{:: 'authz-show-details' | translate}}
+                </td>
+                <td ng-if="policy.details.loaded" class="kc-action-cell" data-ng-click="showDetails(policy);">
+                    {{:: 'authz-hide-details' | translate}}
+                </td>
+            </tr>
+            <tr ng-if="policy.details && policy.details.loaded" ng-repeat-end="">
+                <td colspan="4">
+                    <div id="details">
+                        <table class="table kc-authz-table-expanded table-striped">
+                            <thead>
+                            <tr>
+                                <th>Dependent Permissions</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>
+                                    <span data-ng-show="policy.dependentPolicies && !policy.dependentPolicies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
+                                    <ul ng-repeat="dep in policy.dependentPolicies" data-ng-show="policy.dependentPolicies.length > 0">
+                                        <li>
+                                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{dep.type}}/{{dep.id}}">{{dep.name}}</a>
+                                        </li>
+                                    </ul>
+                                </td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </td>
             </tr>
             <tr data-ng-show="(policies | filter:search).length == 0">
                 <td class="text-muted" colspan="3" data-ng-show="search.name">{{:: 'no-results' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
index f61c6e9..ef20ae9 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-detail.html
@@ -47,9 +47,7 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}}</label>
 
                 <div class="col-md-6">
-                    <select ui-select2 id="reqActions" ng-model="resource.scopes" data-placeholder="{{:: 'authz-select-scope' | translate}}..." multiple>
-                        <option ng-repeat="scope in scopes" value="{{scope.name}}" ng-selected="true">{{scope.name}}</option>
-                    </select>
+                    <input type="hidden" ui-select2="scopesUiSelect" id="reqActions" data-ng-model="resource.scopes" data-placeholder="{{:: 'authz-select-scope' | translate}}..." multiple/>
                 </div>
 
                 <kc-tooltip>{{:: 'authz-resource-scopes.tooltip' | translate}}</kc-tooltip>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
index b1c3978..1f8e1bd 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
@@ -39,8 +39,13 @@
                                     <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
                                 </div>
                             </div>
+                            <div class="input-group">
+                                <select class="form-control search" data-ng-model="detailsFilter" data-ng-change="searchQuery();">
+                                    <option value="" selected>Hide Details</option>
+                                    <option value="true">Show Details</option>
+                                </select>
+                            </div>
                         </div>
-
                         <div class="pull-right">
                             <a id="createResource" class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/create">{{:: 'create' | translate}}</a>
                         </div>
@@ -52,9 +57,7 @@
                 <th>{{:: 'type' | translate}}</th>
                 <th>{{:: 'authz-uri' | translate}}</th>
                 <th>{{:: 'authz-owner' | translate}}</th>
-                <th>{{:: 'authz-scopes' | translate}}</th>
-                <th>{{:: 'authz-permissions' | translate}}</th>
-                <th>{{:: 'actions' | translate}}</th>
+                <th colspan="2">{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
         <tfoot data-ng-show="resources && (resources.length >= query.max || query.first > 0)">
@@ -64,37 +67,67 @@
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="resources.length < query.max">{{:: 'next-page' | translate}}</button>
+                    <select class="first" data-ng-model="query.max"
+                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
+                    </select>
                 </div>
             </td>
         </tr>
         </tfoot>
         <tbody>
-            <tr ng-repeat="resource in resources | filter:search | orderBy:'name'">
+            <tr ng-repeat-start="resource in resources | filter:search | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/{{resource._id}}">{{resource.name}}</a></td>
                 <td>
                     <span data-ng-show="resource.type">{{resource.type}}</span>
                     <span data-ng-show="!resource.type">{{:: 'authz-no-type-defined' | translate}}</span>
                 </td>
-                <td>{{resource.uri}}</td>
-                <td>{{resource.owner.name}}</td>
                 <td>
-                    <span data-ng-show="!resource.scopes.length">{{:: 'authz-no-scopes-assigned' | translate}}</span>
-                    <span data-ng-show="resource.scopes.length > 0">
-                        <span ng-repeat="scope in resource.scopes">
-                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/{{scope.id}}">{{scope.name}}</a>{{$last ? '' : ', '}}
-                        </span>
-                    </span>
+                    <span data-ng-show="resource.uri">{{resource.uri}}</span>
+                    <span data-ng-show="!resource.uri">{{:: 'authz-no-uri-defined' | translate}}</span>
                 </td>
-                <td>
-                    <span data-ng-show="!resource.policies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
-                    <span data-ng-show="resource.policies.length > 0">
-                        <span ng-repeat="policy in resource.policies">
-                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a>{{$last ? '' : ', '}}
-                        </span>
-                    </span>
+                <td>{{resource.owner.name}}</td>
+                <td ng-if="!resource.details.loaded" class="kc-action-cell" data-ng-click="showDetails(resource);">
+                    {{:: 'authz-show-details' | translate}}
+                </td>
+                <td ng-if="resource.details.loaded" class="kc-action-cell" data-ng-click="showDetails(resource);">
+                    {{:: 'authz-hide-details' | translate}}
+                </td>
+                <td class="kc-action-cell" ng-click="createPolicy(resource);">
+                    {{:: 'authz-create-permission' | translate}}
                 </td>
-                <td class="kc-action-cell" style="vertical-align: middle">
-                    <button class="btn btn-default btn-block btn-sm" ng-click="createPolicy(resource);">{{:: 'authz-create-permission' | translate}}</button>
+            </tr>
+            <tr ng-if="resource.details && resource.details.loaded" ng-repeat-end="">
+                <td colspan="6">
+                    <div id="details">
+                        <table class="table kc-authz-table-expanded table-striped">
+                            <thead>
+                                <tr>
+                                    <th>Scopes</th>
+                                    <th>Associated Permissions</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td>
+                                        <span data-ng-show="resource.scopes && !resource.scopes.length">{{:: 'authz-no-scopes-assigned' | translate}}</span>
+                                        <ul ng-repeat="scope in resource.scopes" data-ng-show="resource.scopes.length > 0">
+                                            <li>
+                                                <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/{{scope.id}}">{{scope.name}}</a>
+                                            </li>
+                                        </ul>
+                                    </td>
+                                    <td>
+                                        <span data-ng-show="resource.policies && !resource.policies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
+                                        <ul ng-repeat="policy in resource.policies" data-ng-show="resource.policies.length > 0">
+                                            <li>
+                                                <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a>
+                                            </li>
+                                        </ul>
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
                 </td>
             </tr>
             <tr data-ng-show="(resources | filter:search).length == 0">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
index 7886129..ff8bb14 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
@@ -14,6 +14,12 @@
                                     <i class="fa fa-search" id="scopeSearch" type="submit" data-ng-click="firstPage()"></i>
                                 </div>
                             </div>
+                            <div class="input-group">
+                                <select class="form-control search" data-ng-model="detailsFilter" data-ng-change="showDetails();">
+                                    <option value="" selected>Hide Details</option>
+                                    <option value="true">Show Details</option>
+                                </select>
+                            </div>
                         </div>
                         <div class="pull-right">
                             <a id="createScope" class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/create">{{:: 'create' | translate}}</a>
@@ -23,43 +29,68 @@
             </tr>
             <tr data-ng-hide="scopes.length == 0">
                 <th>{{:: 'name' | translate}}</th>
-                <th>{{:: 'authz-resources' | translate}}</th>
-                <th>{{:: 'authz-permissions' | translate}}</th>
-                <th>{{:: 'actions' | translate}}</th>
+                <th colspan="2">{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
         <tfoot data-ng-show="scopes && (scopes.length >= query.max || query.first > 0)">
         <tr>
-            <td colspan="7">
+            <td colspan="8">
                 <div class="table-nav">
                     <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
                     <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
                     <button data-ng-click="nextPage()" class="next" ng-disabled="scopes.length < query.max">{{:: 'next-page' | translate}}</button>
+                    <select class="first" data-ng-model="query.max"
+                            ng-options="size for size in listSizes" data-ng-change="firstPage()">
+                    </select>
                 </div>
             </td>
         </tr>
         </tfoot>
         <tbody>
-            <tr ng-repeat="scope in scopes | filter:search | orderBy:'name'">
+            <tr ng-repeat-start="scope in scopes | filter:search | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/{{scope.id}}">{{scope.name}}</a></td>
-                <td>
-                    <span data-ng-show="!scope.resources.length">{{:: 'authz-no-resources-assigned' | translate}}</span>
-                    <span data-ng-show="scope.resources.length > 0">
-                        <span ng-repeat="resource in scope.resources">
-                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/{{resource._id}}">{{resource.name}}</a>{{$last ? '' : ', '}}
-                        </span>
-                    </span>
+                <td ng-if="!scope.details.loaded" class="kc-action-cell" data-ng-click="showDetails(scope);">
+                    {{:: 'authz-show-details' | translate}}
+                </td>
+                <td ng-if="scope.details.loaded" class="kc-action-cell" data-ng-click="showDetails(scope);">
+                    {{:: 'authz-hide-details' | translate}}
                 </td>
-                <td>
-                    <span data-ng-show="!scope.policies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
-                    <span data-ng-show="scope.policies.length > 0">
-                        <span ng-repeat="policy in scope.policies">
-                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a>{{$last ? '' : ', '}}
-                        </span>
-                    </span>
+                <td class="kc-action-cell" ng-click="createPolicy(scope);">
+                    {{:: 'authz-create-permission' | translate}}
                 </td>
-                <td class="kc-action-cell" style="vertical-align: middle">
-                    <button class="btn btn-default btn-block btn-sm" ng-click="createPolicy(scope);">{{:: 'authz-create-permission' | translate}}</button>
+            </tr>
+            <tr ng-if="scope.details && scope.details.loaded" ng-repeat-end="">
+                <td colspan="3">
+                    <div id="details">
+                        <table class="table kc-authz-table-expanded table-striped">
+                            <thead>
+                            <tr>
+                                <th>Resources</th>
+                                <th>Associated Permissions</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>
+                                    <span data-ng-show="scope.resources && !scope.resources.length">{{:: 'authz-no-resources-assigned' | translate}}</span>
+                                    <ul ng-repeat="resource in scope.resources" data-ng-show="scope.resources.length > 0">
+                                        <li>
+                                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/{{resource._id}}">{{resource.name}}</a>
+                                        </li>
+                                    </ul>
+                                </td>
+                                <td>
+                                    <span data-ng-show="scope.policies && !scope.policies.length">{{:: 'authz-no-permission-assigned' | translate}}</span>
+                                    <ul ng-repeat="policy in scope.policies" data-ng-show="scope.policies.length > 0">
+                                        <li>
+                                            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a>
+                                        </li>
+                                    </ul>
+                                </td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
                 </td>
             </tr>
             <tr data-ng-show="(scopes | filter:search).length == 0">
diff --git a/themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css b/themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
index 2eb155e..6f72a78 100755
--- a/themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
+++ b/themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
@@ -390,4 +390,13 @@ h1 i {
     float: left;
     margin-left: 2%;
     width: 25%;
+}
+
+table.kc-authz-table-expanded {
+    margin-top: 0px !important;
+}
+
+.no-gutter > [class*='col-'] {
+    padding-right:0!important;
+    padding-left:0!important;
 }
\ No newline at end of file