keycloak-aplcache

Changes

Details

diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyAdminResource.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyAdminResource.java
index 0cfb0f9..0a5acce 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyAdminResource.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/aggregated/AggregatePolicyAdminResource.java
@@ -19,8 +19,8 @@
 package org.keycloak.authorization.policy.provider.aggregated;
 
 import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -30,19 +30,13 @@ import java.util.List;
  */
 public class AggregatePolicyAdminResource implements PolicyProviderAdminService {
 
-    private final ResourceServer resourceServer;
-
-    public AggregatePolicyAdminResource(ResourceServer resourceServer) {
-        this.resourceServer = resourceServer;
-    }
-
     @Override
-    public void onCreate(Policy policy) {
+    public void onCreate(Policy policy, AbstractPolicyRepresentation representation) {
         verifyCircularReference(policy, new ArrayList<>());
     }
 
     @Override
-    public void onUpdate(Policy policy) {
+    public void onUpdate(Policy policy, AbstractPolicyRepresentation representation) {
         verifyCircularReference(policy, new ArrayList<>());
     }
 
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 3e86973..24bb09d 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
@@ -49,8 +49,8 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
-        return new AggregatePolicyAdminResource(resourceServer);
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
+        return new AggregatePolicyAdminResource();
     }
 
     @Override
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 8cb0029..8f7e631 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
@@ -40,7 +40,7 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return null;
     }
 
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 b4a5099..617727f 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
@@ -42,7 +42,7 @@ public class JSPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return null;
     }
 
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 d7a6b2b..b6ffd74 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
@@ -1,13 +1,17 @@
 package org.keycloak.authorization.policy.provider.resource;
 
+import java.util.Map;
+
 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;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -32,8 +36,51 @@ public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
-        return null;
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
+        return new PolicyProviderAdminService<ResourcePermissionRepresentation>() {
+            @Override
+            public void onCreate(Policy policy, ResourcePermissionRepresentation representation) {
+                updateResourceType(policy, representation);
+            }
+
+            @Override
+            public void onUpdate(Policy policy, ResourcePermissionRepresentation representation) {
+                updateResourceType(policy, representation);
+            }
+
+            private void updateResourceType(Policy policy, ResourcePermissionRepresentation representation) {
+                //TODO: remove this check once we migrate to new API
+                if (representation != null) {
+                    Map<String, String> config = policy.getConfig();
+
+                    config.compute("defaultResourceType", (key, value) -> {
+                        String resourceType = representation.getResourceType();
+                        return resourceType != null ? representation.getResourceType() : null;
+                    });
+
+                    policy.setConfig(config);
+                }
+            }
+
+            @Override
+            public void onRemove(Policy policy) {
+
+            }
+
+            @Override
+            public Class<ResourcePermissionRepresentation> getRepresentationType() {
+                return ResourcePermissionRepresentation.class;
+            }
+
+            @Override
+            public ResourcePermissionRepresentation toRepresentation(Policy policy) {
+                ResourcePermissionRepresentation representation = new ResourcePermissionRepresentation();
+
+                representation.setResourceType(policy.getConfig().get("defaultResourceType"));
+
+                return representation;
+            }
+        };
     }
 
     @Override
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 33db2d5..ab262d1 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
@@ -42,7 +42,6 @@ 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>
@@ -67,7 +66,7 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return null;
     }
 
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 0678eb3..1c28a5f 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,12 +2,14 @@ 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;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -32,8 +34,33 @@ public class ScopePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
-        return null;
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
+        return new PolicyProviderAdminService<ScopePermissionRepresentation>() {
+            @Override
+            public void onCreate(Policy policy, ScopePermissionRepresentation representation) {
+
+            }
+
+            @Override
+            public void onUpdate(Policy policy, ScopePermissionRepresentation representation) {
+
+            }
+
+            @Override
+            public void onRemove(Policy policy) {
+
+            }
+
+            @Override
+            public Class<ScopePermissionRepresentation> getRepresentationType() {
+                return ScopePermissionRepresentation.class;
+            }
+
+            @Override
+            public ScopePermissionRepresentation toRepresentation(Policy policy) {
+                return new ScopePermissionRepresentation();
+            }
+        };
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
index 96c1d24..e62602f 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
@@ -20,6 +20,7 @@ package org.keycloak.authorization.policy.provider.time;
 
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 
 import java.text.SimpleDateFormat;
 
@@ -29,7 +30,7 @@ import java.text.SimpleDateFormat;
 public class TimePolicyAdminResource implements PolicyProviderAdminService {
 
     @Override
-    public void onCreate(Policy policy) {
+    public void onCreate(Policy policy, AbstractPolicyRepresentation representation) {
         validateConfig(policy);
     }
 
@@ -44,7 +45,7 @@ public class TimePolicyAdminResource implements PolicyProviderAdminService {
     }
 
     @Override
-    public void onUpdate(Policy policy) {
+    public void onUpdate(Policy policy, AbstractPolicyRepresentation representation) {
         validateConfig(policy);
     }
 
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 94c5aad..4e9fd9e 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
@@ -32,7 +32,7 @@ public class TimePolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return new TimePolicyAdminResource();
     }
 
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 09345ec..a89830f 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
@@ -62,7 +62,7 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return null;
     }
 
diff --git a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyAdminResource.java b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyAdminResource.java
index c6e5701..f334789 100644
--- a/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyAdminResource.java
+++ b/authz/policy/drools/src/main/java/org/keycloak/authorization/policy/provider/drools/DroolsPolicyAdminResource.java
@@ -17,8 +17,8 @@
 package org.keycloak.authorization.policy.provider.drools;
 
 import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.kie.api.runtime.KieContainer;
 
@@ -33,21 +33,19 @@ import javax.ws.rs.core.Response;
  */
 public class DroolsPolicyAdminResource implements PolicyProviderAdminService {
 
-    private final ResourceServer resourceServer;
     private final DroolsPolicyProviderFactory factory;
 
-    public DroolsPolicyAdminResource(ResourceServer resourceServer, DroolsPolicyProviderFactory factory) {
-        this.resourceServer = resourceServer;
+    public DroolsPolicyAdminResource(DroolsPolicyProviderFactory factory) {
         this.factory = factory;
     }
 
     @Override
-    public void onCreate(Policy policy) {
+    public void onCreate(Policy policy, AbstractPolicyRepresentation representation) {
         this.factory.update(policy);
     }
 
     @Override
-    public void onUpdate(Policy policy) {
+    public void onUpdate(Policy policy, AbstractPolicyRepresentation representation) {
         this.factory.update(policy);
     }
 
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 ce0f834..d3dda33 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
@@ -49,8 +49,8 @@ public class DroolsPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
-        return new DroolsPolicyAdminResource(resourceServer, this);
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
+        return new DroolsPolicyAdminResource(this);
     }
 
     @Override
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java
new file mode 100644
index 0000000..ccd5ee1
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.representations.idm.authorization;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class AbstractPolicyRepresentation {
+
+    private String id;
+    private String name;
+    private String description;
+    private String type;
+    private Set<String> policies;
+    private Set<String> resources;
+    private Set<String> scopes;
+    private Logic logic = Logic.POSITIVE;
+    private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
+
+    public String getId() {
+        return this.id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public DecisionStrategy getDecisionStrategy() {
+        return this.decisionStrategy;
+    }
+
+    public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
+        this.decisionStrategy = decisionStrategy;
+    }
+
+    public Logic getLogic() {
+        return logic;
+    }
+
+    public void setLogic(Logic logic) {
+        this.logic = logic;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Set<String> getPolicies() {
+        return policies;
+    }
+
+    public void addPolicies(String... id) {
+        if (this.policies == null) {
+            this.policies = new HashSet<>();
+        }
+        this.policies.addAll(Arrays.asList(id));
+    }
+
+    public Set<String> getResources() {
+        return resources;
+    }
+
+    public void addResource(String id) {
+        if (this.resources == null) {
+            this.resources = new HashSet<>();
+        }
+        this.resources.add(id);
+    }
+
+    public Set<String> getScopes() {
+        return scopes;
+    }
+
+    public void addScopes(String... id) {
+        if (this.scopes == null) {
+            this.scopes = new HashSet<>();
+        }
+        this.scopes.addAll(Arrays.asList(id));
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final AbstractPolicyRepresentation policy = (AbstractPolicyRepresentation) o;
+        return Objects.equals(getId(), policy.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getId());
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/ResourcePermissionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/ResourcePermissionRepresentation.java
new file mode 100644
index 0000000..ebc4cec
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/ResourcePermissionRepresentation.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.representations.idm.authorization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ResourcePermissionRepresentation extends AbstractPolicyRepresentation {
+
+    private String resourceType;
+
+    public void setResourceType(String resourceType) {
+        this.resourceType = resourceType;
+    }
+
+    public String getResourceType() {
+        return resourceType;
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/ScopePermissionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/ScopePermissionRepresentation.java
new file mode 100644
index 0000000..f9d9767
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/ScopePermissionRepresentation.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.representations.idm.authorization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class ScopePermissionRepresentation extends AbstractPolicyRepresentation {
+}
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 9cd4e74..fba7eb5 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
@@ -285,6 +285,7 @@ public class CachedPolicyStore implements PolicyStore {
             public void removeScope(Scope scope) {
                 getDelegateForUpdate().removeScope(getStoreFactory().getScopeStore().findById(scope.getId(), cached.getResourceServerId()));
                 cached.removeScope(scope);
+                scopes.remove(scope);
             }
 
             @Override
@@ -297,6 +298,7 @@ public class CachedPolicyStore implements PolicyStore {
             public void removeAssociatedPolicy(Policy associatedPolicy) {
                 getDelegateForUpdate().removeAssociatedPolicy(getStoreFactory().getPolicyStore().findById(associatedPolicy.getId(), cached.getResourceServerId()));
                 cached.removeAssociatedPolicy(associatedPolicy);
+                associatedPolicies.remove(associatedPolicy);
             }
 
             @Override
@@ -309,6 +311,7 @@ public class CachedPolicyStore implements PolicyStore {
             public void removeResource(Resource resource) {
                 getDelegateForUpdate().removeResource(getStoreFactory().getResourceStore().findById(resource.getId(), cached.getResourceServerId()));
                 cached.removeResource(resource);
+                resources.remove(resource);
             }
 
             @Override
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
index 775cf64..c7bef79 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/entities/CachedPolicy.java
@@ -160,7 +160,7 @@ public class CachedPolicy implements Policy, Serializable {
 
     @Override
     public void removeResource(Resource resource) {
-        this.resourcesIds.add(resource.getId());
+        this.resourcesIds.remove(resource.getId());
     }
 
     @Override
diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderAdminService.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderAdminService.java
index d26208e..ec7b6c9 100644
--- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderAdminService.java
+++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderAdminService.java
@@ -19,15 +19,24 @@
 package org.keycloak.authorization.policy.provider;
 
 import org.keycloak.authorization.model.Policy;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
-public interface PolicyProviderAdminService {
+public interface PolicyProviderAdminService<R extends AbstractPolicyRepresentation> {
 
-    void onCreate(Policy policy);
+    void onCreate(Policy policy, R representation);
 
-    void onUpdate(Policy policy);
+    void onUpdate(Policy policy, R representation);
 
     void onRemove(Policy policy);
+
+    default AbstractPolicyRepresentation toRepresentation(Policy policy) {
+        return null;
+    }
+
+    default Class<R> getRepresentationType() {
+        return null;
+    }
 }
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 f7041b5..8385964 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
@@ -19,7 +19,6 @@
 package org.keycloak.authorization.policy.provider;
 
 import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.provider.ProviderFactory;
 
@@ -34,5 +33,5 @@ public interface PolicyProviderFactory extends ProviderFactory<PolicyProvider> {
 
     PolicyProvider create(AuthorizationProvider authorization);
 
-    PolicyProviderAdminService getAdminResource(ResourceServer resourceServer);
+    PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization);
 }
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 2557bfd..3693b9e 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
@@ -25,6 +25,7 @@ import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
+import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceServerStore;
 import org.keycloak.authorization.store.ResourceStore;
@@ -92,6 +93,7 @@ import org.keycloak.representations.idm.UserConsentRepresentation;
 import org.keycloak.representations.idm.UserFederationMapperRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
@@ -2101,6 +2103,168 @@ public class RepresentationToModel {
         return null;
     }
 
+    public static Policy toModel(AbstractPolicyRepresentation representation, ResourceServer resourceServer, AuthorizationProvider authorization) {
+        String type = representation.getType();
+        PolicyProvider provider = authorization.getProvider(type);
+
+        if (provider == null) {
+            //TODO: temporary, remove this check on future versions as drools type is now deprecated
+            if ("drools".equalsIgnoreCase(type)) {
+                type = "rules";
+            }
+            if (authorization.getProvider(type) == null) {
+                throw new RuntimeException("Unknown polucy type [" + type + "]. Could not find a provider for this type.");
+            }
+        }
+
+        PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
+        Policy existing;
+
+        if (representation.getId() != null) {
+            existing = policyStore.findById(representation.getId(), resourceServer.getId());
+        } else {
+            existing = policyStore.findByName(representation.getName(), resourceServer.getId());
+        }
+
+        if (existing != null) {
+            existing.setName(representation.getName());
+            existing.setDescription(representation.getDescription());
+            existing.setDecisionStrategy(representation.getDecisionStrategy());
+            existing.setLogic(representation.getLogic());
+
+            updatePolicy(existing, representation, authorization);
+
+            return existing;
+        }
+
+        Policy model = policyStore.create(representation.getName(), type, resourceServer);
+
+        model.setDescription(representation.getDescription());
+        model.setDecisionStrategy(representation.getDecisionStrategy());
+        model.setLogic(representation.getLogic());
+
+        updatePolicy(model, representation, authorization);
+
+        representation.setId(model.getId());
+
+        return model;
+    }
+
+    private static void updatePolicy(Policy policy, AbstractPolicyRepresentation representation, AuthorizationProvider authorization) {
+        ResourceServer resourceServer = policy.getResourceServer();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        Set<String> newResources = representation.getResources();
+
+        if (newResources != null && !newResources.isEmpty()) {
+            Set<Resource> associatedResources = policy.getResources();
+            String newResourceId = newResources.iterator().next();
+
+            if (newResourceId != null) {
+                Resource newResource = storeFactory.getResourceStore().findById(newResourceId, resourceServer.getId());
+
+                if (newResource == null) {
+                    throw new RuntimeException("Resource with id [" + newResourceId + "] does not exist");
+                }
+
+                if (!associatedResources.isEmpty()) {
+                    Resource associatedResource = associatedResources.iterator().next();
+
+                    if (!associatedResource.getId().equals(newResource.getId())) {
+                        policy.removeResource(associatedResource);
+                    }
+                }
+
+                policy.addResource(newResource);
+            } else {
+                for (Resource resource : new ArrayList<>(associatedResources)) {
+                    policy.removeResource(resource);
+                }
+            }
+        } else {
+            for (Resource associatedResource : new HashSet<Resource>(policy.getResources())) {
+                policy.removeResource(associatedResource);
+            }
+        }
+
+        PolicyStore policyStore = storeFactory.getPolicyStore();
+        Set<String> policies = representation.getPolicies();
+
+        for (String policyId : policies) {
+            boolean hasPolicy = false;
+
+            for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
+                if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
+                    hasPolicy = true;
+                }
+            }
+
+
+            if (!hasPolicy) {
+                Policy associatedPolicy = policyStore.findById(policyId, resourceServer.getId());
+
+                if (associatedPolicy == null) {
+                    associatedPolicy = policyStore.findByName(policyId, resourceServer.getId());
+                }
+
+                policy.addAssociatedPolicy(associatedPolicy);
+            }
+        }
+
+        for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
+            boolean hasPolicy = false;
+
+            for (String policyId : policies) {
+                if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
+                    hasPolicy = true;
+                }
+            }
+            if (!hasPolicy) {
+                policy.removeAssociatedPolicy(policyModel);
+                ;
+            }
+        }
+
+        Set<String> newScopes = representation.getScopes();
+
+        if (newScopes != null && !newScopes.isEmpty()) {
+            for (String scopeId : newScopes) {
+                boolean hasScope = false;
+
+                for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
+                    if (scopeModel.getId().equals(scopeId)) {
+                        hasScope = true;
+                    }
+                }
+                if (!hasScope) {
+                    Scope scope = storeFactory.getScopeStore().findById(scopeId, resourceServer.getId());
+
+                    if (scope == null) {
+                        storeFactory.getScopeStore().findByName(scopeId, resourceServer.getId());
+                    }
+
+                    policy.addScope(scope);
+                }
+            }
+
+            for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
+                boolean hasScope = false;
+
+                for (String scopeId : newScopes) {
+                    if (scopeModel.getId().equals(scopeId)) {
+                        hasScope = true;
+                    }
+                }
+                if (!hasScope) {
+                    policy.removeScope(scopeModel);
+                }
+            }
+        } else {
+            for (Scope associatedScope : new HashSet<Scope>(policy.getScopes())) {
+                policy.removeScope(associatedScope);
+            }
+        }
+    }
+
     public static Policy toModel(PolicyRepresentation policy, ResourceServer resourceServer, AuthorizationProvider authorization) {
         String type = policy.getType();
         PolicyProvider provider = authorization.getProvider(type);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PermissionResourceService.java b/services/src/main/java/org/keycloak/authorization/admin/PermissionResourceService.java
new file mode 100644
index 0000000..6d4583d
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authorization/admin/PermissionResourceService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.admin;
+
+import static org.keycloak.models.utils.RepresentationToModel.toModel;
+
+import java.io.IOException;
+
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PermissionResourceService extends PolicyResourceService {
+
+    public PermissionResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+        super(policy, resourceServer, authorization, auth);
+    }
+
+    @Override
+    protected void doUpdate(Policy policy, String payload) {
+        String type = policy.getType();
+        PolicyProviderAdminService provider = getPolicyProviderAdminResource(type);
+        AbstractPolicyRepresentation representation = toRepresentation(type, payload, provider);
+
+        policy = toModel(representation, policy.getResourceServer(), authorization);
+
+        try {
+            provider.onUpdate(policy, representation);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private AbstractPolicyRepresentation toRepresentation(String type, String payload, PolicyProviderAdminService provider) {
+        Class<? extends AbstractPolicyRepresentation> representationType = provider.getRepresentationType();
+
+        if (representationType == null) {
+            throw new RuntimeException("Policy provider for type [" + type + "] returned a null representation type.");
+        }
+
+        AbstractPolicyRepresentation representation;
+
+        try {
+            representation = JsonSerialization.readValue(payload, representationType);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to deserialize JSON using policy provider for type [" + type + "].", e);
+        }
+        return representation;
+    }
+
+    @Override
+    protected Object toRepresentation(Policy policy) {
+        PolicyProviderAdminService provider = getPolicyProviderAdminResource(policy.getType());
+        return toRepresentation(policy, provider.toRepresentation(policy));
+    }
+
+    private AbstractPolicyRepresentation toRepresentation(Policy policy, AbstractPolicyRepresentation representation) {
+        representation.setId(policy.getId());
+        representation.setName(policy.getName());
+        representation.setDescription(policy.getDescription());
+        representation.setType(policy.getType());
+        representation.setDecisionStrategy(policy.getDecisionStrategy());
+        representation.setLogic(policy.getLogic());
+        representation.addResource(policy.getResources().stream().map(resource -> resource.getId()).findFirst().orElse(null));
+        representation.addPolicies(policy.getAssociatedPolicies().stream().map(associated -> associated.getId()).toArray(value -> new String[value]));
+        representation.addScopes(policy.getScopes().stream().map(associated -> associated.getId()).toArray(value -> new String[value]));
+
+        return representation;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
new file mode 100644
index 0000000..32a607f
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authorization/admin/PermissionService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.admin;
+
+import java.util.List;
+import java.util.Map;
+
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.services.resources.admin.RealmAuth;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PermissionService extends PolicyService {
+    public PermissionService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+        super(resourceServer, authorization, auth);
+    }
+
+    @Override
+    protected Object doCreatePolicyTypeResource(String type) {
+        return new PermissionTypeService(type, resourceServer, authorization, auth);
+    }
+
+    @Override
+    protected PolicyResourceService doCreatePolicyResource(Policy policy) {
+        return new PermissionResourceService(policy, resourceServer, authorization, auth);
+    }
+
+    @Override
+    protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
+        filters.put("permission", new String[] {Boolean.TRUE.toString()});
+        return super.doSearch(firstResult, maxResult, filters);
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PermissionTypeService.java b/services/src/main/java/org/keycloak/authorization/admin/PermissionTypeService.java
new file mode 100644
index 0000000..d2b598a
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authorization/admin/PermissionTypeService.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.admin;
+
+import static org.keycloak.models.utils.RepresentationToModel.toModel;
+
+import java.io.IOException;
+
+import javax.ws.rs.Path;
+
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation;
+import org.keycloak.services.resources.admin.RealmAuth;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PermissionTypeService extends PolicyService {
+
+    private final String type;
+
+    PermissionTypeService(String type, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+        super(resourceServer, authorization, auth);
+        this.type = type;
+    }
+
+    @Path("/provider")
+    public Object getPolicyAdminResourceProvider() {
+        PolicyProviderAdminService resource = getPolicyProviderAdminResource(type);
+
+        ResteasyProviderFactory.getInstance().injectProperties(resource);
+
+        return resource;
+    }
+
+    @Override
+    protected Object doCreatePolicyResource(Policy policy) {
+        return new PermissionResourceService(policy, resourceServer,authorization, auth);
+    }
+
+    @Override
+    protected Object doCreate(String payload) {
+        PolicyProviderAdminService provider = getPolicyProviderAdminResource(type);
+        AbstractPolicyRepresentation representation = toRepresentation(type, payload, provider);
+
+        Policy policy = toModel(representation, this.resourceServer, authorization);
+
+        if (provider != null) {
+            try {
+                provider.onCreate(policy, representation);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        return representation;
+    }
+
+    private AbstractPolicyRepresentation toRepresentation(String type, String payload, PolicyProviderAdminService provider) {
+        Class<? extends AbstractPolicyRepresentation> representationType = provider.getRepresentationType();
+
+        if (representationType == null) {
+            throw new RuntimeException("Policy provider for type [" + type + "] returned a null representation type.");
+        }
+
+        AbstractPolicyRepresentation representation;
+
+        try {
+            representation = JsonSerialization.readValue(payload, representationType);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to deserialize JSON using policy provider for type [" + type + "].", e);
+        }
+        return representation;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java
new file mode 100644
index 0000000..003db4c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyResourceService.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.admin;
+
+import static org.keycloak.models.utils.RepresentationToModel.toModel;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+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.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.Policy;
+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.StoreFactory;
+import org.keycloak.models.utils.ModelToRepresentation;
+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 org.keycloak.util.JsonSerialization;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PolicyResourceService {
+
+    private final Policy policy;
+    protected final ResourceServer resourceServer;
+    protected final AuthorizationProvider authorization;
+    protected final RealmAuth auth;
+
+    public PolicyResourceService(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+        this.policy = policy;
+        this.resourceServer = resourceServer;
+        this.authorization = authorization;
+        this.auth = auth;
+    }
+
+    @PUT
+    @Consumes("application/json")
+    @Produces("application/json")
+    @NoCache
+    public Response update(String payload) {
+        this.auth.requireManage();
+
+        doUpdate(policy, payload);
+
+        return Response.status(Status.CREATED).build();
+    }
+
+    protected void doUpdate(Policy policy, String payload) {
+        PolicyRepresentation representation;
+
+        try {
+            representation = JsonSerialization.readValue(payload, PolicyRepresentation.class);
+        } catch (IOException cause) {
+            throw new RuntimeException("Failed to deserialize representation", cause);
+        }
+
+        representation.setId(policy.getId());
+
+        policy = toModel(representation, resourceServer, authorization);
+
+        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType());
+
+        if (resource != null) {
+            try {
+                resource.onUpdate(policy, null);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @DELETE
+    public Response delete() {
+        this.auth.requireManage();
+        StoreFactory storeFactory = authorization.getStoreFactory();
+        PolicyStore policyStore = storeFactory.getPolicyStore();
+        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType());
+
+        if (resource != null) {
+            try {
+                resource.onRemove(policy);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
+            if (dependentPolicy.getAssociatedPolicies().size() == 1) {
+                policyStore.delete(dependentPolicy.getId());
+            } else {
+                dependentPolicy.removeAssociatedPolicy(policy);
+            }
+        });
+
+        policyStore.delete(policy.getId());
+
+        return Response.noContent().build();
+    }
+
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response findById() {
+        this.auth.requireView();
+        return Response.ok(toRepresentation(policy)).build();
+    }
+
+    protected Object toRepresentation(Policy model) {
+        return ModelToRepresentation.toRepresentation(model);
+    }
+
+    @Path("/dependentPolicies")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getDependentPolicies() {
+        this.auth.requireView();
+        List<Policy> policies = authorization.getStoreFactory().getPolicyStore().findDependentPolicies(policy.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("/scopes")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getScopes() {
+        this.auth.requireView();
+        return Response.ok(policy.getScopes().stream().map(scope -> {
+            ScopeRepresentation representation = new ScopeRepresentation();
+
+            representation.setId(scope.getId());
+            representation.setName(scope.getName());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("/resources")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getResources() {
+        this.auth.requireView();
+
+        return Response.ok(policy.getResources().stream().map(resource -> {
+            ResourceRepresentation representation = new ResourceRepresentation();
+
+            representation.setId(resource.getId());
+            representation.setName(resource.getName());
+
+            return representation;
+        }).collect(Collectors.toList())).build();
+    }
+
+    @Path("/associatedPolicies")
+    @GET
+    @Produces("application/json")
+    @NoCache
+    public Response getAssociatedPolicies() {
+        this.auth.requireView();
+
+        return Response.ok(policy.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();
+    }
+
+    protected PolicyProviderAdminService getPolicyProviderAdminResource(String policyType) {
+        PolicyProviderFactory providerFactory = authorization.getProviderFactory(policyType);
+
+        if (providerFactory != null) {
+            return providerFactory.getAdminResource(resourceServer, authorization);
+        }
+
+        return null;
+    }
+}
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 8982a29..3151b49 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -17,9 +17,9 @@
  */
 package org.keycloak.authorization.admin;
 
-import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
 import static org.keycloak.models.utils.RepresentationToModel.toModel;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -29,14 +29,13 @@ 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.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
@@ -48,24 +47,22 @@ 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.ScopeStore;
 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 org.keycloak.util.JsonSerialization;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 public class PolicyService {
 
-    private final ResourceServer resourceServer;
-    private final AuthorizationProvider authorization;
-    private final RealmAuth auth;
+    protected final ResourceServer resourceServer;
+    protected final AuthorizationProvider authorization;
+    protected final RealmAuth auth;
 
     public PolicyService(ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
         this.resourceServer = resourceServer;
@@ -73,210 +70,80 @@ public class PolicyService {
         this.auth = auth;
     }
 
-    @POST
-    @Consumes("application/json")
-    @Produces("application/json")
-    @NoCache
-    public Response create(PolicyRepresentation representation) {
+    @Path("{type}")
+    public Object getResource(@PathParam("type") String type) {
         this.auth.requireManage();
-        Policy policy = toModel(representation, this.resourceServer, authorization);
-        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
+        PolicyProviderFactory providerFactory = authorization.getProviderFactory(type);
 
-        if (resource != null) {
-            try {
-                resource.onCreate(policy);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
+        if (providerFactory != null) {
+            return doCreatePolicyTypeResource(type);
         }
 
-        representation.setId(policy.getId());
-
-        return Response.status(Status.CREATED).entity(representation).build();
-    }
-
-    @Path("{id}")
-    @PUT
-    @Consumes("application/json")
-    @Produces("application/json")
-    @NoCache
-    public Response update(@PathParam("id") String id, PolicyRepresentation representation) {
-        this.auth.requireManage();
-        representation.setId(id);
-        StoreFactory storeFactory = authorization.getStoreFactory();
-        Policy policy = storeFactory.getPolicyStore().findById(representation.getId(), resourceServer.getId());
+        Policy policy = authorization.getStoreFactory().getPolicyStore().findById(type, resourceServer.getId());
 
         if (policy == null) {
             return Response.status(Status.NOT_FOUND).build();
         }
 
-        policy = toModel(representation, resourceServer, authorization);
-
-        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
-
-        if (resource != null) {
-            try {
-                resource.onUpdate(policy);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        return Response.status(Status.CREATED).build();
+        return doCreatePolicyResource(policy);
     }
 
-    @Path("{id}")
-    @DELETE
-    public Response delete(@PathParam("id") String id) {
-        this.auth.requireManage();
-        StoreFactory storeFactory = authorization.getStoreFactory();
-        PolicyStore policyStore = storeFactory.getPolicyStore();
-        Policy policy = policyStore.findById(id, resourceServer.getId());
-
-        if (policy == null) {
-            return Response.status(Status.NOT_FOUND).build();
-        }
-
-        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
-
-        if (resource != null) {
-            try {
-                resource.onRemove(policy);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        policyStore.findDependentPolicies(id, resourceServer.getId()).forEach(dependentPolicy -> {
-            if (dependentPolicy.getAssociatedPolicies().size() == 1) {
-                policyStore.delete(dependentPolicy.getId());
-            } else {
-                dependentPolicy.removeAssociatedPolicy(policy);
-            }
-        });
-
-        policyStore.delete(policy.getId());
-
-        return Response.noContent().build();
+    protected Object doCreatePolicyTypeResource(String type) {
+        return new PolicyTypeService(type, resourceServer, authorization, auth);
     }
 
-    @Path("{id}")
-    @GET
-    @Produces("application/json")
-    @NoCache
-    public Response findById(@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(toRepresentation(model)).build();
+    protected Object doCreatePolicyResource(Policy policy) {
+        return new PolicyResourceService(policy, resourceServer, authorization, auth);
     }
 
-    @Path("{id}/dependentPolicies")
-    @GET
-    @Produces("application/json")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.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();
+    @Deprecated
+    public Response create(String payload) {
+        this.auth.requireManage();
+        return Response.status(Status.CREATED).entity(doCreate(payload)).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());
+    protected Object doCreate(String payload) {
+        PolicyRepresentation representation;
 
-        if (model == null) {
-            return Response.status(Status.NOT_FOUND).build();
+        try {
+            representation = JsonSerialization.readValue(payload, PolicyRepresentation.class);
+        } catch (IOException cause) {
+            throw new RuntimeException("Failed to deserialize representation", cause);
         }
 
-        return Response.ok(model.getScopes().stream().map(scope -> {
-            ScopeRepresentation representation = new ScopeRepresentation();
-
-            representation.setId(scope.getId());
-            representation.setName(scope.getName());
+        create(representation);
 
-            return representation;
-        }).collect(Collectors.toList())).build();
+        return representation;
     }
 
-    @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());
+    public void create(PolicyRepresentation representation) {
+        Policy policy = toModel(representation, this.resourceServer, authorization);
+        PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType());
 
-        if (model == null) {
-            return Response.status(Status.NOT_FOUND).build();
+        if (resource != null) {
+            try {
+                resource.onCreate(policy, null);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
         }
 
-        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();
+        representation.setId(policy.getId());
     }
 
-    @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();
+    protected Object toRepresentation(Policy model) {
+        return ModelToRepresentation.toRepresentation(model);
     }
 
     @Path("/search")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
-    public Response find(@QueryParam("name") String name) {
+    public Response findByName(@QueryParam("name") String name) {
         this.auth.requireView();
         StoreFactory storeFactory = authorization.getStoreFactory();
 
@@ -294,7 +161,7 @@ public class PolicyService {
     }
 
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public Response findAll(@QueryParam("policyId") String id,
                             @QueryParam("name") String name,
@@ -363,15 +230,20 @@ public class PolicyService {
         }
 
         return Response.ok(
-                policyStore.findByResourceServer(search, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
-                        .map(policy -> toRepresentation(policy))
-                        .collect(Collectors.toList()))
+                doSearch(firstResult, maxResult, search))
                 .build();
     }
 
+    protected List<Object> doSearch(Integer firstResult, Integer maxResult, Map<String, String[]> filters) {
+        PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
+        return policyStore.findByResourceServer(filters, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : Constants.DEFAULT_MAX_RESULTS).stream()
+                .map(policy -> toRepresentation(policy))
+                .collect(Collectors.toList());
+    }
+
     @Path("providers")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public Response findPolicyProviders() {
         this.auth.requireView();
@@ -400,17 +272,11 @@ public class PolicyService {
         return resource;
     }
 
-    @Path("{policyType}")
-    public Object getPolicyTypeResource(@PathParam("policyType") String policyType) {
-        this.auth.requireView();
-        return getPolicyProviderAdminResource(policyType, this.authorization);
-    }
-
-    private PolicyProviderAdminService getPolicyProviderAdminResource(String policyType, AuthorizationProvider authorization) {
+    protected PolicyProviderAdminService getPolicyProviderAdminResource(String policyType) {
         PolicyProviderFactory providerFactory = authorization.getProviderFactory(policyType);
 
         if (providerFactory != null) {
-            return providerFactory.getAdminResource(this.resourceServer);
+            return providerFactory.getAdminResource(resourceServer, authorization);
         }
 
         return null;
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
new file mode 100644
index 0000000..7d3f8b4
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyTypeService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.authorization.admin;
+
+import javax.ws.rs.Path;
+
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.authorization.AuthorizationProvider;
+import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+import org.keycloak.services.resources.admin.RealmAuth;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class PolicyTypeService extends PolicyService {
+
+    private final String type;
+
+    PolicyTypeService(String type, ResourceServer resourceServer, AuthorizationProvider authorization, RealmAuth auth) {
+        super(resourceServer, authorization, auth);
+        this.type = type;
+    }
+
+    @Path("/provider")
+    public Object getPolicyAdminResourceProvider() {
+        PolicyProviderAdminService resource = getPolicyProviderAdminResource(type);
+
+        ResteasyProviderFactory.getInstance().injectProperties(resource);
+
+        return resource;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
index 52d6a38..ffd67b6 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java
@@ -17,6 +17,22 @@
  */
 package org.keycloak.authorization.admin;
 
+import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.ResourceServer;
@@ -38,21 +54,6 @@ import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
 import org.keycloak.services.resources.admin.RealmAuth;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.io.IOException;
-import java.util.HashMap;
-
-import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
-
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -171,6 +172,16 @@ public class ResourceServerService {
         return resource;
     }
 
+    @Path("/permission")
+    public Object getPermissionTypeResource() {
+        this.auth.requireView();
+        PermissionService resource = new PermissionService(this.resourceServer, this.authorization, this.auth);
+
+        ResteasyProviderFactory.getInstance().injectProperties(resource);
+
+        return resource;
+    }
+
     private void createDefaultPermission(ResourceRepresentation resource, PolicyRepresentation policy) {
         PolicyRepresentation defaultPermission = new PolicyRepresentation();
 
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 b3a0475..8e07ee2 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
@@ -47,7 +47,7 @@ public class TestPolicyProviderFactory implements PolicyProviderFactory {
     }
 
     @Override
-    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
+    public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
         return null;
     }
 
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 e40fcec..5cb9f1f 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
@@ -646,7 +646,7 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
     };
 });
 
-module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerPolicy, PolicyProvider, client) {
+module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerPermission, PolicyProvider, client) {
     $scope.realm = realm;
     $scope.client = client;
     $scope.policyProviders = [];
@@ -654,7 +654,6 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
     $scope.query = {
         realm: realm.realm,
         client : client.id,
-        permission: true,
         max : 20,
         first : 0
     };
@@ -705,7 +704,7 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
     $scope.searchQuery = function() {
         $scope.searchLoaded = false;
 
-        ResourceServerPolicy.query($scope.query, function(data) {
+        ResourceServerPermission.query($scope.query, function(data) {
             $scope.policies = data;
             $scope.searchLoaded = true;
             $scope.lastSearch = $scope.query.search;
@@ -723,7 +722,7 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
 
         policy.details = {loaded: false};
 
-        ResourceServerPolicy.associatedPolicies({
+        ResourceServerPermission.associatedPolicies({
             realm : $route.current.params.realm,
             client : client.id,
             id : policy.id
@@ -758,7 +757,7 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
                     policy = $scope.policy;
                 }
 
-                $http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/resolveModules'
+                $http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/provider/resolveModules'
                         , policy).success(function(data) {
                             $scope.drools.moduleNames = data;
                             $scope.resolveSessions();
@@ -766,7 +765,7 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
             }
 
             $scope.resolveSessions = function() {
-                $http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/resolveSessions'
+                $http.post(authUrl + '/admin/realms/'+ $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/policy/rules/provider/resolveSessions'
                         , $scope.policy).success(function(data) {
                             $scope.drools.moduleSessions = data;
                         });
@@ -789,7 +788,7 @@ module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http
     }, realm, client, $scope);
 });
 
-module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $route, $location, realm, client, PolicyController, ResourceServerPolicy, ResourceServerResource) {
+module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $route, $location, realm, client, PolicyController, ResourceServerPermission, ResourceServerResource) {
     PolicyController.onInit({
         getPolicyType : function() {
             return "resource";
@@ -848,7 +847,7 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
                         max : 20,
                         first : 0
                     };
-                    ResourceServerPolicy.query($scope.query, function(response) {
+                    ResourceServerPermission.searchPolicies($scope.query, function(response) {
                         data.results = response;
                         query.callback(data);
                     });
@@ -860,59 +859,89 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
             };
 
             $scope.applyToResourceType = function() {
-                if ($scope.policy.config.default) {
-                    $scope.policy.config.resources = [];
+                if ($scope.applyToResourceTypeFlag) {
+                    $scope.selectedResource = null;
                 } else {
-                    $scope.policy.config.defaultResourceType = null;
+                    $scope.policy.resourceType = null;
                 }
             }
         },
 
         onInitUpdate : function(policy) {
-            policy.config.default = eval(policy.config.default);
-            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];
-            });
+            if (!policy.resourceType) {
+                $scope.selectedResource = {};
+                ResourceServerPermission.resources({
+                    realm: $route.current.params.realm,
+                    client: client.id,
+                    id: policy.id
+                }, function (resources) {
+                    resources[0].text = resources[0].name;
+                    $scope.selectedResource = resources[0];
+                    var copy = angular.copy($scope.selectedResource);
+                    $scope.$watch('selectedResource', function() {
+                        if (!angular.equals($scope.selectedResource, copy)) {
+                            $scope.changed = true;
+                        }
+                    }, true);
+                });
+            } else {
+                $scope.applyToResourceTypeFlag = true;
+            }
 
-            policy.config.applyPolicies = [];
-            ResourceServerPolicy.associatedPolicies({
+            $scope.selectedPolicies = [];
+            ResourceServerPermission.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]);
+                    $scope.selectedPolicies.push(policies[i]);
+                    var copy = angular.copy($scope.selectedPolicies);
+                    $scope.$watch('selectedPolicies', function() {
+                        if (!angular.equals($scope.selectedPolicies, copy)) {
+                            $scope.changed = true;
+                        }
+                    }, true);
                 }
             });
         },
 
         onUpdate : function() {
-            if ($scope.policy.config.resources && $scope.policy.config.resources._id) {
-                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            if ($scope.selectedResource && $scope.selectedResource._id) {
+                $scope.policy.resources = [];
+                $scope.policy.resources.push($scope.selectedResource._id);
             } else {
-                delete $scope.policy.config.resources
+                delete $scope.policy.resources
             }
 
             var policies = [];
 
-            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
-                policies.push($scope.policy.config.applyPolicies[i].id);
+            for (i = 0; i < $scope.selectedPolicies.length; i++) {
+                policies.push($scope.selectedPolicies[i].id);
             }
 
-            $scope.policy.config.applyPolicies = JSON.stringify(policies);
+            $scope.policy.policies = policies;
+            delete $scope.policy.config;
         },
 
         onInitCreate : function(newPolicy) {
             newPolicy.decisionStrategy = 'UNANIMOUS';
-            newPolicy.config = {};
-            newPolicy.config.resources = null;
+            $scope.selectedResource = null;
+            var copy = angular.copy($scope.selectedResource);
+            $scope.$watch('selectedResource', function() {
+                if (!angular.equals($scope.selectedResource, copy)) {
+                    $scope.changed = true;
+                }
+            }, true);
+
+            $scope.selectedPolicies = null;
+            var copy = angular.copy($scope.selectedPolicies);
+            $scope.$watch('selectedPolicies', function() {
+                if (!angular.equals($scope.selectedPolicies, copy)) {
+                    $scope.changed = true;
+                }
+            }, true);
 
             var resourceId = $location.search()['rsrid'];
 
@@ -923,25 +952,27 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
                     rsrid : resourceId
                 }, function(data) {
                     data.text = data.name;
-                    $scope.policy.config.resources = data;
+                    $scope.selectedResource = data;
                 });
             }
         },
 
         onCreate : function() {
-            if ($scope.policy.config.resources && $scope.policy.config.resources._id) {
-                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            if ($scope.selectedResource && $scope.selectedResource._id) {
+                $scope.policy.resources = [];
+                $scope.policy.resources.push($scope.selectedResource._id);
             } else {
-                delete $scope.policy.config.resources
+                delete $scope.policy.resources
             }
 
             var policies = [];
 
-            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
-                policies.push($scope.policy.config.applyPolicies[i].id);
+            for (i = 0; i < $scope.selectedPolicies.length; i++) {
+                policies.push($scope.selectedPolicies[i].id);
             }
 
-            $scope.policy.config.applyPolicies = JSON.stringify(policies);
+            $scope.policy.policies = policies;
+            delete $scope.policy.config;
         }
     }, realm, client, $scope);
 });
@@ -1046,20 +1077,21 @@ module.controller('ResourceServerPolicyScopeDetailCtrl', function($scope, $route
             };
 
             $scope.selectResource = function() {
-                $scope.policy.config.scopes = null;
-                if ($scope.policy.config.resources) {
+                $scope.selectedScopes = null;
+                if ($scope.policy.resources) {
                     ResourceServerResource.scopes({
                         realm: $route.current.params.realm,
                         client: client.id,
-                        rsrid: $scope.policy.config.resources._id
+                        rsrid: $scope.policy.resources._id
                     }, function (data) {
-                        $scope.policy.config.resources.scopes = data;
+                        $scope.resourceScopes = data;
                     });
                 }
             }
         },
 
         onInitUpdate : function(policy) {
+            $scope.selectedScopes = [];
             ResourceServerPolicy.resources({
                 realm : $route.current.params.realm,
                 client : client.id,
@@ -1079,44 +1111,44 @@ module.controller('ResourceServerPolicyScopeDetailCtrl', function($scope, $route
                                 deep: false
                             }, function (resource) {
                                 resource[0].text = resource[0].name;
-                                $scope.policy.config.resources = resource[0];
+                                $scope.policy.resources = resource[0];
                                 ResourceServerResource.scopes({
                                     realm: $route.current.params.realm,
                                     client: client.id,
                                     rsrid: resource[0]._id
                                 }, function (scopes) {
-                                    $scope.policy.config.resources.scopes = scopes;
+                                    $scope.resourceScopes = scopes;
                                 });
                                 ResourceServerPolicy.scopes({
                                     realm: $route.current.params.realm,
                                     client: client.id,
                                     id: policy.id
                                 }, function (scopes) {
-                                    $scope.policy.config.scopes = [];
+                                    $scope.selectedScopes = [];
                                     for (i = 0; i < scopes.length; i++) {
-                                        $scope.policy.config.scopes.push(scopes[i].id);
+                                        $scope.selectedScopes.push(scopes[i].id);
                                     }
                                 });
                             });
                         });
                     }
                 } else {
-                    $scope.policy.config.resources = null;
+                    $scope.policy.resources = null;
                     ResourceServerPolicy.scopes({
                         realm : $route.current.params.realm,
                         client : client.id,
                         id : policy.id
                     }, function(scopes) {
-                        $scope.policy.config.scopes = [];
+                        $scope.selectedScopes = [];
                         for (i = 0; i < scopes.length; i++) {
                             scopes[i].text = scopes[i].name;
-                            $scope.policy.config.scopes.push(scopes[i]);
+                            $scope.selectedScopes.push(scopes[i]);
                         }
                     });
                 }
             });
 
-            policy.config.applyPolicies = [];
+            policy.policies = [];
             ResourceServerPolicy.associatedPolicies({
                 realm : $route.current.params.realm,
                 client : client.id,
@@ -1124,43 +1156,42 @@ module.controller('ResourceServerPolicyScopeDetailCtrl', function($scope, $route
             }, function(policies) {
                 for (i = 0; i < policies.length; i++) {
                     policies[i].text = policies[i].name;
-                    $scope.policy.config.applyPolicies.push(policies[i]);
+                    $scope.policy.policies.push(policies[i]);
                 }
             });
         },
 
         onUpdate : function() {
-            if ($scope.policy.config.resources != null) {
-                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            if ($scope.policy.resources != null) {
+                $scope.policy.resources = [$scope.policy.resources._id];
             } else {
-                $scope.policy.config.resources = JSON.stringify([""]);
+                delete $scope.policy.resources;
             }
 
             var scopes = [];
 
-            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);
+            for (i = 0; i < $scope.selectedScopes.length; i++) {
+                if ($scope.selectedScopes[i].id) {
+                    scopes.push($scope.selectedScopes[i].id);
                 } else {
-                    scopes.push($scope.policy.config.scopes[i]);
+                    scopes.push($scope.selectedScopes[i]);
                 }
             }
 
-            $scope.policy.config.scopes = JSON.stringify(scopes);
+            $scope.policy.scopes = scopes;
 
             var policies = [];
 
-            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
-                policies.push($scope.policy.config.applyPolicies[i].id);
+            for (i = 0; i < $scope.policy.policies.length; i++) {
+                policies.push($scope.policy.policies[i].id);
             }
 
-            $scope.policy.config.applyPolicies = JSON.stringify(policies);
+            $scope.policy.policies = policies;
         },
 
         onInitCreate : function(newPolicy) {
             newPolicy.decisionStrategy = 'UNANIMOUS';
-            newPolicy.config = {};
-            newPolicy.config.resources = null;
+            newPolicy.resources = null;
 
             var scopeId = $location.search()['scpid'];
 
@@ -1171,38 +1202,39 @@ module.controller('ResourceServerPolicyScopeDetailCtrl', function($scope, $route
                     id: scopeId,
                 }, function (data) {
                     data.text = data.name;
-                    if (!$scope.policy.config.scopes) {
-                        $scope.policy.config.scopes = [];
+                    if (!$scope.policy.scopes) {
+                        $scope.policy.scopes = [];
                     }
-                    $scope.policy.config.scopes.push(data);
+                    $scope.policy.scopes.push(data);
                 });
             }
         },
 
         onCreate : function() {
-            if ($scope.policy.config.resources != null) {
-                $scope.policy.config.resources = JSON.stringify([$scope.policy.config.resources._id]);
+            if ($scope.policy.resources != null) {
+                $scope.policy.resources = [$scope.policy.resources._id];
             }
 
             var scopes = [];
 
-            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);
+            for (i = 0; i < $scope.selectedScopes.length; i++) {
+                if ($scope.selectedScopes[i].id) {
+                    scopes.push($scope.selectedScopes[i].id);
                 } else {
-                    scopes.push($scope.policy.config.scopes[i]);
+                    scopes.push($scope.selectedScopes[i]);
                 }
             }
 
-            $scope.policy.config.scopes = JSON.stringify(scopes);
+            $scope.policy.scopes = scopes;
 
             var policies = [];
 
-            for (i = 0; i < $scope.policy.config.applyPolicies.length; i++) {
-                policies.push($scope.policy.config.applyPolicies[i].id);
+            for (i = 0; i < $scope.policy.policies.length; i++) {
+                policies.push($scope.policy.policies[i].id);
             }
 
-            $scope.policy.config.applyPolicies = JSON.stringify(policies);
+            $scope.policy.policies = policies;
+            delete $scope.policy.config;
         }
     }, realm, client, $scope);
 });
@@ -1743,7 +1775,7 @@ module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $r
     }, realm, client, $scope);
 });
 
-module.service("PolicyController", function($http, $route, $location, ResourceServer, ResourceServerPolicy, AuthzDialog, Notifications) {
+module.service("PolicyController", function($http, $route, $location, ResourceServer, ResourceServerPolicy, ResourceServerPermission, AuthzDialog, Notifications) {
 
     var PolicyController = {};
 
@@ -1754,6 +1786,12 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
             }
         }
 
+        var service = ResourceServerPolicy;
+
+        if (delegate.isPermission()) {
+            service = ResourceServerPermission;
+        }
+
         $scope.realm = realm;
         $scope.client = client;
 
@@ -1799,7 +1837,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                         if (delegate.onCreate) {
                             delegate.onCreate();
                         }
-                        ResourceServerPolicy.save({realm : realm.realm, client : client.id}, $scope.policy, function(data) {
+                        service.save({realm : realm.realm, client : client.id, type: $scope.policy.type}, $scope.policy, function(data) {
                             if (delegate.isPermission()) {
                                 $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + $scope.policy.type + "/" + data.id);
                                 Notifications.success("The permission has been created.");
@@ -1819,9 +1857,10 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                     }
                 }
             } else {
-                ResourceServerPolicy.get({
+                service.get({
                     realm: realm.realm,
                     client : client.id,
+                    type: delegate.getPolicyType(),
                     id: $route.current.params.id
                 }, function(data) {
                     $scope.originalPolicy = data;
@@ -1845,7 +1884,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                             if (delegate.onUpdate) {
                                 delegate.onUpdate();
                             }
-                            ResourceServerPolicy.update({realm : realm.realm, client : client.id, id : $scope.policy.id}, $scope.policy, function() {
+                            service.update({realm : realm.realm, client : client.id, type: $scope.policy.type, id : $scope.policy.id}, $scope.policy, function() {
                                 $route.reload();
                                 if (delegate.isPermission()) {
                                     Notifications.success("The permission has been updated.");
@@ -1871,7 +1910,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                 $scope.remove = function() {
                     var msg = "";
 
-                    ResourceServerPolicy.dependentPolicies({
+                    service.dependentPolicies({
                         realm : $route.current.params.realm,
                         client : client.id,
                         id : $scope.policy.id
@@ -1887,7 +1926,7 @@ module.service("PolicyController", function($http, $route, $location, ResourceSe
                         }
 
                         AuthzDialog.confirmDeleteWithMsg($scope.policy.name, "Policy", msg, function() {
-                            ResourceServerPolicy.delete({realm : $scope.realm.realm, client : $scope.client.id, id : $scope.policy.id}, null, function() {
+                            service.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.");
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 1c4f584..92219bb 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
@@ -36,10 +36,11 @@ module.factory('ResourceServerScope', function($resource) {
 });
 
 module.factory('ResourceServerPolicy', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:id', {
+    return $resource(authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/:type/:id', {
         realm : '@realm',
         client: '@client',
-        id : '@id'
+        id : '@id',
+        type: '@type'
     }, {
         'update' : {method : 'PUT'},
         'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/search', method : 'GET'},
@@ -50,6 +51,23 @@ module.factory('ResourceServerPolicy', function($resource) {
     });
 });
 
+module.factory('ResourceServerPermission', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/permission/:type/:id', {
+        realm : '@realm',
+        client: '@client',
+        type: '@type',
+        id : '@id'
+    }, {
+        'update' : {method : 'PUT'},
+        'search' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/permission/search', method : 'GET'},
+        'searchPolicies' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy', method : 'GET', isArray: true},
+        '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/permission/:id/scopes', method : 'GET', isArray: true},
+        'resources' : {url: authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/permission/:id/resources', method : 'GET', isArray: true}
+    });
+});
+
 module.factory('PolicyProvider', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/clients/:client/authz/resource-server/policy/providers', {
         realm : '@realm',
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 10e3170..7a5ba6d 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
@@ -29,25 +29,25 @@
                 <kc-tooltip>{{:: 'authz-permission-description.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="policy.config.default">{{:: 'authz-permission-resource-apply-to-resource-type' | translate}}</label>
+                <label class="col-md-2 control-label" for="applyToResourceTypeFlag">{{:: 'authz-permission-resource-apply-to-resource-type' | translate}}</label>
                 <div class="col-md-6">
-                    <input ng-model="policy.config.default" id="policy.config.default" onoffswitch data-ng-click="applyToResourceType()"/>
+                    <input ng-model="applyToResourceTypeFlag" id="applyToResourceTypeFlag" onoffswitch data-ng-click="applyToResourceType()"/>
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-resource-apply-to-resource-type.tooltip' | translate}}</kc-tooltip>
             </div>
-            <div class="form-group clearfix" data-ng-hide="policy.config.default">
+            <div class="form-group clearfix" data-ng-hide="applyToResourceTypeFlag">
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resources' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <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"/>
+                    <input type="hidden" ui-select2="resourcesUiSelect" id="reqActions" data-ng-model="selectedResource" data-placeholder="{{:: 'authz-select-resource' | translate}}..." data-ng-required="!applyToResourceTypeFlag"/>
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-resource-resource.tooltip' | translate}}</kc-tooltip>
             </div>
-            <div class="form-group clearfix" data-ng-show="policy.config.default">
-                <label class="col-md-2 control-label" for="policy.config.defaultResourceType">{{:: 'authz-resource-type' | translate}} <span class="required">*</span></label>
+            <div class="form-group clearfix" data-ng-show="applyToResourceTypeFlag">
+                <label class="col-md-2 control-label" for="policy.resourceType">{{:: 'authz-resource-type' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <input class="form-control" type="text" id="policy.config.defaultResourceType" name="policy.config.defaultResourceType" data-ng-model="policy.config.defaultResourceType" data-ng-required="policy.config.default">
+                    <input class="form-control" type="text" id="policy.resourceType" name="policy.resourceType" data-ng-model="policy.resourceType" data-ng-required="applyToResourceTypeFlag">
                 </div>
 
                 <kc-tooltip>{{:: 'authz-permission-resource-type.tooltip' | translate}}</kc-tooltip>
@@ -56,7 +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">
-                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
+                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="selectedPolicies" 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 90a3dc6..1754fe5 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,27 +32,28 @@
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-resource' | translate}}</label>
 
                 <div class="col-md-6">
-                    <input type="hidden" ui-select2="resourcesUiSelect" data-ng-change="selectResource()" id="reqActions" data-ng-model="policy.config.resources" data-placeholder="{{:: 'authz-any-resource' | translate}}..." />
+                    <input type="hidden" ui-select2="resourcesUiSelect" data-ng-change="selectResource()" id="reqActions" data-ng-model="policy.resources" data-placeholder="{{:: 'authz-any-resource' | translate}}..." />
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-scope-resource.tooltip' | translate}}</kc-tooltip>
             </div>
-            <div class="form-group clearfix" data-ng-show="policy.config.resources">
+            <div class="form-group clearfix" data-ng-show="policy.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 id="reqActions2"
-                            data-ng-model="policy.config.scopes"
+                            data-ng-model="selectedScopes"
                             data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple
-                            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"/>
+                            data-ng-required="policy.resources != null">
+                        <option ng-repeat="scope in resourceScopes" value="{{scope.id}}">{{scope.name}}</option>
+                    </select>
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
             </div>
-            <div class="form-group clearfix" data-ng-show="!policy.config.resources">
+            <div class="form-group clearfix" data-ng-show="!policy.resources">
                 <label class="col-md-2 control-label" for="reqActions">{{:: 'authz-scopes' | translate}} <span class="required">*</span></label>
 
                 <div class="col-md-6">
-                    <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" />
+                    <input type="hidden" ui-select2="scopesUiSelect" id="reqActions" data-ng-model="selectedScopes" data-placeholder="{{:: 'authz-any-scope' | translate}}..." multiple data-ng-required="policy.resources == null" />
                 </div>
                 <kc-tooltip>{{:: 'authz-permission-scope-scope.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -60,7 +61,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">
-                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.config.applyPolicies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
+                    <input type="hidden" ui-select2="policiesUiSelect" id="reqActions" data-ng-model="policy.policies" data-placeholder="{{:: 'authz-select-a-policy' | translate}}..." multiple required />
                 </div>
 
                 <kc-tooltip>{{:: 'authz-policy-apply-policy.tooltip' | translate}}</kc-tooltip>