keycloak-aplcache

remove scope

6/16/2017 12:26:43 PM

Changes

Details

diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
index 8382155..fa2f9a2 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationAuth.java
@@ -31,12 +31,15 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.representations.JsonWebToken;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.clientregistration.policy.RegistrationAuth;
 import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyException;
 import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyManager;
+import org.keycloak.services.managers.RealmManager;
 import org.keycloak.util.TokenUtil;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -231,42 +234,70 @@ public class ClientRegistrationAuth {
         return initialAccessModel;
     }
 
-    private boolean hasRole(String... role) {
+    private boolean hasRole(String... roles) {
         try {
-            Map<String, Object> otherClaims = jwt.getOtherClaims();
-            if (otherClaims != null) {
-                Map<String, Map<String, List<String>>> resourceAccess = (Map<String, Map<String, List<String>>>) jwt.getOtherClaims().get("resource_access");
-                if (resourceAccess == null) {
-                    return false;
-                }
+            if (jwt.getIssuedFor().equals(Constants.ADMIN_CLI_CLIENT_ID)
+                    || jwt.getIssuedFor().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
+                return hasRoleInModel(roles);
 
-                List<String> roles = null;
+            } else {
+                return hasRoleInToken(roles);
+            }
+        } catch (Throwable t) {
+            return false;
+        }
+    }
 
-                Map<String, List<String>> map;
-                if (realm.getName().equals(Config.getAdminRealm())) {
-                    map = resourceAccess.get(realm.getMasterAdminClient().getClientId());
-                } else {
-                    map = resourceAccess.get(Constants.REALM_MANAGEMENT_CLIENT_ID);
-                }
+    private boolean hasRoleInModel(String[] roles) {
+        ClientModel roleNamespace;
+        UserModel user = session.users().getUserById(jwt.getSubject(), realm);
+        if (user == null) {
+            return false;
+        }
+        if (realm.getName().equals(Config.getAdminRealm())) {
+            roleNamespace = realm.getMasterAdminClient();
+        } else {
+            roleNamespace = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+        }
+        for (String role : roles) {
+            RoleModel roleModel = roleNamespace.getRole(role);
+            if (user.hasRole(roleModel)) return true;
+        }
+        return false;
+    }
 
-                if (map != null) {
-                    roles = map.get("roles");
-                }
+    private boolean hasRoleInToken(String[] role) {
+        Map<String, Object> otherClaims = jwt.getOtherClaims();
+        if (otherClaims != null) {
+            Map<String, Map<String, List<String>>> resourceAccess = (Map<String, Map<String, List<String>>>) jwt.getOtherClaims().get("resource_access");
+            if (resourceAccess == null) {
+                return false;
+            }
 
-                if (roles == null) {
-                    return false;
-                }
+            List<String> roles = null;
+
+            Map<String, List<String>> map;
+            if (realm.getName().equals(Config.getAdminRealm())) {
+                map = resourceAccess.get(realm.getMasterAdminClient().getClientId());
+            } else {
+                map = resourceAccess.get(Constants.REALM_MANAGEMENT_CLIENT_ID);
+            }
 
-                for (String r : role) {
-                    if (roles.contains(r)) {
-                        return true;
-                    }
+            if (map != null) {
+                roles = map.get("roles");
+            }
+
+            if (roles == null) {
+                return false;
+            }
+
+            for (String r : role) {
+                if (roles.contains(r)) {
+                    return true;
                 }
             }
-            return false;
-        } catch (Throwable t) {
-            return false;
         }
+        return false;
     }
 
     private boolean authenticateClient(ClientModel client) {
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 21df21f..95dc02a 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -159,7 +159,6 @@ public class RealmManager {
             ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
             adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
         }
-        adminConsole.addScopeMapping(adminRole);
     }
 
     protected void setupAdminConsoleLocaleMapper(RealmModel realm) {
@@ -194,7 +193,6 @@ public class RealmManager {
                 ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
                 adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
             }
-            adminCli.addScopeMapping(adminRole);
         }
 
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index ba7eccc..88650c1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -834,7 +834,7 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RequiredActionProviderRepresentation> getRequiredActions() {
-        auth.realm().requireViewRealm();
+        auth.requireAnyAdminRole();
 
         List<RequiredActionProviderRepresentation> list = new LinkedList<>();
         for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
index c619669..ae7d519 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
@@ -140,7 +140,7 @@ public class ClientRoleMappingsResource {
 
         Set<RoleModel> available = client.getRoles();
         available = available.stream().filter(r ->
-                canMapRole(r)
+                auth.roles().canMapRole(r)
         ).collect(Collectors.toSet());
         return getAvailableRoles(user, available);
     }
@@ -174,23 +174,13 @@ public class ClientRoleMappingsResource {
             if (roleModel == null || !roleModel.getId().equals(role.getId())) {
                 throw new NotFoundException("Role not found");
             }
-            checkMapRolePermission(roleModel);
+            auth.roles().requireMapRole(roleModel);
             user.grantRole(roleModel);
         }
         adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(roles).success();
 
     }
 
-    private void checkMapRolePermission(RoleModel roleModel) {
-        if (!canMapRole(roleModel)) {
-            throw new ForbiddenException();
-        }
-    }
-
-    private boolean canMapRole(RoleModel roleModel) {
-        return auth.roles().canMapRole(roleModel);
-    }
-
     /**
          * Delete client-level roles from user role mapping
          *
@@ -210,7 +200,7 @@ public class ClientRoleMappingsResource {
                     ClientModel client = (ClientModel) roleModel.getContainer();
                     if (!client.getId().equals(this.client.getId())) continue;
                 }
-                checkMapRolePermission(roleModel);
+                auth.roles().requireMapRole(roleModel);
                 user.deleteRoleMapping(roleModel);
                 roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
@@ -222,7 +212,7 @@ public class ClientRoleMappingsResource {
                     throw new NotFoundException("Role not found");
                 }
 
-                checkMapRolePermission(roleModel);
+                auth.roles().requireMapRole(roleModel);
                 try {
                     user.deleteRoleMapping(roleModel);
                 } catch (ModelException me) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
index 839aa41..1e8105d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
@@ -76,13 +76,20 @@ public class ClientTemplatesResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<ClientTemplateRepresentation> getClientTemplates() {
-        auth.clients().requireView();
+        auth.clients().requireListTemplates();
 
         List<ClientTemplateRepresentation> rep = new ArrayList<>();
         List<ClientTemplateModel> clientModels = realm.getClientTemplates();
 
+        boolean viewable = auth.clients().canViewTemplates();
         for (ClientTemplateModel clientModel : clientModels) {
-            rep.add(ModelToRepresentation.toRepresentation(clientModel));
+            if (viewable) rep.add(ModelToRepresentation.toRepresentation(clientModel));
+            else {
+                ClientTemplateRepresentation tempRep = new ClientTemplateRepresentation();
+                tempRep.setName(clientModel.getName());
+                tempRep.setId(clientModel.getId());
+                tempRep.setProtocol(clientModel.getProtocol());
+            }
         }
         return rep;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java
index 56be4cf..19abaf4 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissionEvaluator.java
@@ -25,6 +25,8 @@ import org.keycloak.services.resources.admin.AdminAuth;
 public interface AdminPermissionEvaluator {
     RealmPermissionEvaluator realm();
 
+    void requireAnyAdminRole();
+
     AdminAuth adminAuth();
 
     RolePermissionEvaluator roles();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java
index 61a8bff..ef1c1ae 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java
@@ -35,6 +35,10 @@ public class AdminPermissions {
         return new MgmtPermissions(session, realm, adminsRealm, admin);
     }
 
+    public static RealmsPermissionEvaluator realms(KeycloakSession session, AdminAuth auth) {
+        return new MgmtPermissions(session, auth);
+    }
+
     public static AdminPermissionManagement management(KeycloakSession session, RealmModel realm) {
         return new MgmtPermissions(session, realm);
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
index 39f7b4d..1f41e70 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
@@ -115,16 +115,12 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         String managePermissionName = getManagePermissionName(client);
         Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
         if (managePermission == null) {
-            RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS);
-            Policy manageClientsPolicy = root.roles().rolePolicy(server, role);
-            Helper.addScopePermission(authz, server, managePermissionName, resource, manageScope, manageClientsPolicy);
+            Helper.addEmptyScopePermission(authz, server, managePermissionName, resource, manageScope);
         }
         String viewPermissionName = getViewPermissionName(client);
         Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
         if (viewPermission == null) {
-            RoleModel role = root.getRealmManagementClient().getRole(AdminRoles.VIEW_CLIENTS);
-            Policy viewClientsPolicy = root.roles().rolePolicy(server, role);
-            Helper.addScopePermission(authz, server, viewPermissionName, resource, viewScope, viewClientsPolicy);
+            Helper.addEmptyScopePermission(authz, server, viewPermissionName, resource, viewScope);
         }
         String mapRolePermissionName = getMapRolesPermissionName(client);
         Policy mapRolePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRolePermissionName, server.getId());
@@ -216,7 +212,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             throw new ForbiddenException();
         }
     }
-    public boolean canManageClientDefault() {
+    public boolean canManageClientsDefault() {
         return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS);
     }
     public boolean canViewClientDefault() {
@@ -225,7 +221,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
 
     @Override
     public boolean canManage() {
-        return canManageClientDefault();
+        return canManageClientsDefault();
     }
 
     @Override
@@ -236,7 +232,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     }
     @Override
     public boolean canView() {
-        return canManageClientDefault() || canViewClientDefault();
+        return canManageClientsDefault() || canViewClientDefault();
     }
 
     @Override
@@ -269,25 +265,26 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
 
     @Override
     public boolean canManage(ClientModel client) {
+        if (canManageClientsDefault()) return true;
         if (!root.isAdminSameRealm()) {
-            return canManage();
+            return false;
         }
 
         ResourceServer server = resourceServer(client);
-        if (server == null) return canManage();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
-        if (resource == null) return canManage();
+        if (resource == null) return false;
 
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
         if (policy == null) {
-            return canManage();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return canManage();
+            return false;
         }
 
         Scope scope = manageScope(server);
@@ -303,25 +300,30 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
 
     @Override
     public boolean canView(ClientModel client) {
+        return hasView(client) || canManage(client);
+    }
+
+    private boolean hasView(ClientModel client) {
+        if (canView()) return true;
         if (!root.isAdminSameRealm()) {
-            return canView();
+            return false;
         }
 
         ResourceServer server = resourceServer(client);
-        if (server == null) return canView();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
-        if (resource == null) return canView();
+        if (resource == null) return false;
 
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
         if (policy == null) {
-            return canView();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return canView();
+            return false;
         }
 
         Scope scope = viewScope(server);
@@ -344,7 +346,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
 
     @Override
     public boolean canManageTemplates() {
-        return canManageClientDefault();
+        return canManageClientsDefault();
     }
 
     @Override
@@ -362,7 +364,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
 
     @Override
     public boolean canManage(ClientTemplateModel template) {
-        return canManageClientDefault();
+        return canManageClientsDefault();
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
index 450b074..d3a5213 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionEvaluator.java
@@ -53,5 +53,9 @@ public interface GroupPermissionEvaluator {
 
     void requireManageMembers(GroupModel group);
 
+    boolean canManageMembership(GroupModel group);
+
+    void requireManageMembership(GroupModel group);
+
     Map<String, Boolean> getAccess(GroupModel group);
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
index 5fcfbbb..2ec602c 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissionManagement.java
@@ -33,10 +33,14 @@ public interface GroupPermissionManagement {
 
     Policy viewMembersPermission(GroupModel group);
     Policy manageMembersPermission(GroupModel group);
+
+    Policy manageMembershipPermission(GroupModel group);
+
     Policy viewPermission(GroupModel group);
     Policy managePermission(GroupModel group);
 
     Resource resource(GroupModel group);
 
     Map<String, String> getPermissions(GroupModel group);
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
index 2223802..0475b46 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/GroupPermissions.java
@@ -41,6 +41,7 @@ import java.util.Set;
 class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManagement {
     private static final Logger logger = Logger.getLogger(GroupPermissions.class);
     public static final String MAP_ROLE_SCOPE = "map-role";
+    public static final String MANAGE_MEMBERSHIP_SCOPE = "manage.membership";
     public static final String MANAGE_MEMBERS_SCOPE = "manage.members";
     public static final String VIEW_MEMBERS_SCOPE = "view.members";
     protected final KeycloakSession session;
@@ -68,6 +69,10 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
         return "manage.members.permission.group." + group.getId();
     }
 
+    public static String getManageMembershipPermissionGroup(GroupModel group) {
+        return "manage.membership.permission.group." + group.getId();
+    }
+
     public static String getGroupSuffix(GroupModel group) {
         return ModelToRepresentation.buildGroupPath(group).replace('/', '.');
     }
@@ -88,6 +93,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
         Scope viewScope = root.realmViewScope();
         Scope manageMembersScope = root.initializeRealmScope(MANAGE_MEMBERS_SCOPE);
         Scope viewMembersScope = root.initializeRealmScope(VIEW_MEMBERS_SCOPE);
+        Scope manageMembershipScope = root.initializeRealmScope(MANAGE_MEMBERSHIP_SCOPE);
 
         String groupResourceName = getGroupResourceName(group);
         Resource groupResource = authz.getStoreFactory().getResourceStore().findByName(groupResourceName, server.getId());
@@ -96,19 +102,19 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
             Set<Scope> scopeset = new HashSet<>();
             scopeset.add(manageScope);
             scopeset.add(viewScope);
+            scopeset.add(manageMembershipScope);
+            scopeset.add(manageMembersScope);
             groupResource.updateScopes(scopeset);
         }
         String managePermissionName = getManagePermissionGroup(group);
         Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
         if (managePermission == null) {
-            Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
-            Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
+            Helper.addEmptyScopePermission(authz, server, managePermissionName, groupResource, manageScope);
         }
         String viewPermissionName = getViewPermissionGroup(group);
         Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
         if (viewPermission == null) {
-            Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
-            Helper.addScopePermission(authz, server, viewPermissionName, groupResource, viewScope, viewUsersPolicy);
+            Helper.addEmptyScopePermission(authz, server, viewPermissionName, groupResource, viewScope);
         }
         String manageMembersPermissionName = getManageMembersPermissionGroup(group);
         Policy manageMembersPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembersPermissionName, server.getId());
@@ -120,6 +126,12 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
         if (viewMembersPermission == null) {
             Helper.addEmptyScopePermission(authz, server, viewMembersPermissionName, groupResource, viewMembersScope);
         }
+        String manageMembershipPermissionName = getManageMembershipPermissionGroup(group);
+        Policy manageMembershipPermission = authz.getStoreFactory().getPolicyStore().findByName(manageMembershipPermissionName, server.getId());
+        if (manageMembershipPermission == null) {
+            Helper.addEmptyScopePermission(authz, server, manageMembershipPermissionName, groupResource, manageMembershipScope);
+        }
+
     }
 
     @Override
@@ -200,6 +212,14 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
 
     @Override
+    public Policy manageMembershipPermission(GroupModel group) {
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return null;
+        String manageMembershipPermissionName = getManageMembershipPermissionGroup(group);
+        return authz.getStoreFactory().getPolicyStore().findByName(manageMembershipPermissionName, server.getId());
+    }
+
+    @Override
     public Policy viewPermission(GroupModel group) {
         ResourceServer server = root.realmResourceServer();
         if (server == null) return null;
@@ -231,6 +251,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
         scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(group).getId());
         scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
         scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
+        scopes.put(MANAGE_MEMBERSHIP_SCOPE, manageMembershipPermission(group).getId());
         return scopes;
     }
 
@@ -239,25 +260,26 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
 
     @Override
     public boolean canManage(GroupModel group) {
+        if (canManage()) return true;
         if (!root.isAdminSameRealm()) {
-            return canManage();
+            return false;
         }
 
         ResourceServer server = root.realmResourceServer();
-        if (server == null) return canManage();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
-        if (resource == null) return canManage();
+        if (resource == null) return false;
 
         Policy policy = managePermission(group);
         if (policy == null) {
-            return canManage();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return canManage();
+            return false;
         }
 
         Scope scope = root.realmManageScope();
@@ -272,25 +294,31 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
     @Override
     public boolean canView(GroupModel group) {
+        return hasView(group) || canManage(group);
+    }
+
+    private boolean hasView(GroupModel group) {
+        if (canView()) return true;
+
         if (!root.isAdminSameRealm()) {
-            return canView();
+            return false;
         }
 
         ResourceServer server = root.realmResourceServer();
-        if (server == null) return canView();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
-        if (resource == null) return canView();
+        if (resource == null) return false;
 
         Policy policy = viewPermission(group);
         if (policy == null) {
-            return canView();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then abort
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return canView();
+            return false;
         }
 
         Scope scope = root.realmViewScope();
@@ -335,25 +363,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
 
     private boolean canViewMembersEvaluation(GroupModel group) {
+        if (root.users().canView()) return true;
+
         if (!root.isAdminSameRealm()) {
-            return root.users().canView();
+            return false;
         }
 
         ResourceServer server = root.realmResourceServer();
-        if (server == null) return root.users().canView();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
-        if (resource == null) return root.users().canView();
+        if (resource == null) return false;
 
         Policy policy = viewMembersPermission(group);
         if (policy == null) {
-            return root.users().canView();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return root.users().canView();
+            return false;
         }
 
         Scope scope = authz.getStoreFactory().getScopeStore().findByName(VIEW_MEMBERS_SCOPE, server.getId());
@@ -372,25 +402,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
 
     @Override
     public boolean canManageMembers(GroupModel group) {
+        if (root.users().canManage()) return true;
+
         if (!root.isAdminSameRealm()) {
-            return root.users().canManage();
+            return false;
         }
 
         ResourceServer server = root.realmResourceServer();
-        if (server == null) return root.users().canManage();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
-        if (resource == null) return root.users().canManage();
+        if (resource == null) return false;
 
         Policy policy = manageMembersPermission(group);
         if (policy == null) {
-            return root.users().canManage();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return root.users().canManage();
+            return false;
         }
 
         Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERS_SCOPE, server.getId());
@@ -405,10 +437,47 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
 
     @Override
+    public boolean canManageMembership(GroupModel group) {
+        if (canManage(group)) return true;
+
+        if (!root.isAdminSameRealm()) {
+            return false;
+        }
+
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return false;
+
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+        if (resource == null) return false;
+
+        Policy policy = manageMembershipPermission(group);
+        if (policy == null) {
+            return false;
+        }
+
+        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+        // if no policies attached to permission then just do default behavior
+        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+            return false;
+        }
+
+        Scope scope = authz.getStoreFactory().getScopeStore().findByName(MANAGE_MEMBERSHIP_SCOPE, server.getId());
+        return root.evaluatePermission(resource, scope, server);
+    }
+
+    @Override
+    public void requireManageMembership(GroupModel group) {
+        if (!canManageMembership(group)) {
+            throw new ForbiddenException();
+        }
+    }
+
+    @Override
     public Map<String, Boolean> getAccess(GroupModel group) {
         Map<String, Boolean> map = new HashMap<>();
         map.put("view", canView(group));
         map.put("manage", canManage(group));
+        map.put("manageMembership", canManageMembership(group));
         return map;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java
index a356d05..8c9e584 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java
@@ -40,6 +40,7 @@ import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.services.ForbiddenException;
 import org.keycloak.services.managers.RealmManager;
@@ -51,7 +52,7 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManagement {
+class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManagement, RealmsPermissionEvaluator {
     private static final Logger logger = Logger.getLogger(MgmtPermissions.class);
 
     protected RealmModel realm;
@@ -85,7 +86,21 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
                 && !auth.getRealm().equals(new RealmManager(session).getKeycloakAdminstrationRealm())) {
             throw new ForbiddenException();
         }
-        if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)) {
+        if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
+                || auth.getClient().getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
+            this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser());
+
+        } else {
+            this.identity = new KeycloakIdentity(auth.getToken(), session);
+        }
+    }
+    MgmtPermissions(KeycloakSession session, AdminAuth auth) {
+        this.session = session;
+        this.auth = auth;
+        this.admin = auth.getUser();
+        this.adminsRealm = auth.getRealm();
+        if (auth.getClient().getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
+                || auth.getClient().getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
             this.identity = new UserModelIdentity(auth.getRealm(), auth.getUser());
 
         } else {
@@ -117,17 +132,36 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
 
 
 
+    @Override
+    public void requireAnyAdminRole() {
+        if (!hasAnyAdminRole()) {
+            throw new ForbiddenException();
+        }
+    }
+
     public boolean hasAnyAdminRole() {
         return hasOneAdminRole(AdminRoles.ALL_REALM_ROLES);
     }
 
+    public boolean hasAnyAdminRole(RealmModel realm) {
+        return hasOneAdminRole(realm, AdminRoles.ALL_REALM_ROLES);
+    }
+
     public boolean hasOneAdminRole(String... adminRoles) {
         String clientId;
+        RealmModel realm = this.realm;
+        return hasOneAdminRole(realm, adminRoles);
+    }
+
+    public boolean hasOneAdminRole(RealmModel realm, String... adminRoles) {
+        String clientId;
         RealmManager realmManager = new RealmManager(session);
         if (adminsRealm.equals(realmManager.getKeycloakAdminstrationRealm())) {
             clientId = realm.getMasterAdminClient().getClientId();
+        } else if (adminsRealm.equals(realm)) {
+            clientId = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm)).getClientId();
         } else {
-            clientId = realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())).getClientId();
+            return false;
         }
         for (String adminRole : adminRoles) {
             if (identity.hasClientRole(clientId, adminRole)) return true;
@@ -136,7 +170,6 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
     }
 
 
-
     public boolean isAdminSameRealm() {
         return auth == null || realm.getId().equals(auth.getRealm().getId());
     }
@@ -274,6 +307,33 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage
         }
     }
 
+    @Override
+    public boolean canView(RealmModel realm) {
+        return hasOneAdminRole(realm, AdminRoles.VIEW_REALM, AdminRoles.MANAGE_REALM);
+    }
+
+    @Override
+    public boolean isAdmin(RealmModel realm) {
+        return hasAnyAdminRole(realm);
+    }
+
+    @Override
+    public boolean canCreateRealm() {
+        RealmManager realmManager = new RealmManager(session);
+        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
+           return false;
+        }
+        return identity.hasRealmRole(AdminRoles.CREATE_REALM);
+    }
+
+    @Override
+    public void requireCreateRealm() {
+        if (!canCreateRealm()) {
+            throw new ForbiddenException();
+        }
+    }
+
+
 
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java
index cf350a1..7020667 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissionEvaluator.java
@@ -16,12 +16,14 @@
  */
 package org.keycloak.services.resources.admin.permissions;
 
+import org.keycloak.models.RealmModel;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public interface RealmPermissionEvaluator {
-    boolean canListRealm();
+    boolean canListRealms();
 
     void requireViewRealmNameList();
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java
index 1d54c55..3fc752f 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmPermissions.java
@@ -76,17 +76,18 @@ class RealmPermissions implements RealmPermissionEvaluator {
     }
 
     @Override
-    public boolean canListRealm() {
+    public boolean canListRealms() {
         return root.hasAnyAdminRole();
     }
 
     @Override
     public void requireViewRealmNameList() {
-        if (!canListRealm()) {
+        if (!canListRealms()) {
             throw new ForbiddenException();
         }
     }
 
+
     @Override
     public boolean canManageRealm() {
         return canManageRealmDefault();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmsPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmsPermissionEvaluator.java
new file mode 100644
index 0000000..b58202f
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RealmsPermissionEvaluator.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.services.resources.admin.permissions;
+
+import org.keycloak.models.RealmModel;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface RealmsPermissionEvaluator {
+    boolean canView(RealmModel realm);
+
+    boolean isAdmin(RealmModel realm);
+
+    boolean canCreateRealm();
+
+    void requireCreateRealm();
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
index 83838de..a5fee73 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/RolePermissions.java
@@ -69,10 +69,15 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
        } else {
            ResourceServer server = resourceServer(role);
            if (server == null) return;
+           Policy policy = mapRolePermission(role);
+           if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+           policy = mapClientScopePermission(role);
+           if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+           policy = mapCompositePermission(role);
+           if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+
            Resource resource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(role), server.getId());
            if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
-           Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), server.getId());
-           if (policy != null) authz.getStoreFactory().getPolicyStore().delete(policy.getId());
        }
     }
 
@@ -140,20 +145,22 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
      */
     @Override
     public boolean canMapRole(RoleModel role) {
+        if (root.users().canManageDefault()) return true;
         if (!root.isAdminSameRealm()) {
-            return root.users().canManageDefault();
+            return false;
         }
+
         if (role.getContainer() instanceof ClientModel) {
             if (root.clients().canMapRoles((ClientModel)role.getContainer())) return true;
         }
         if (!isPermissionsEnabled(role)){
-            return root.users().canManageDefault();
+            return false;
         }
 
         ResourceServer resourceServer = getResourceServer(role);
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), resourceServer.getId());
         if (policy.getAssociatedPolicies().isEmpty()) {
-            return root.users().canManageDefault(); // if no policies applied, just do default
+            return false;
         }
 
         Resource roleResource = resource(role);
@@ -216,20 +223,22 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
 
     @Override
     public boolean canMapComposite(RoleModel role) {
+        if (canManageDefault(role)) return true;
+
         if (!root.isAdminSameRealm()) {
-            return canManage(role);
+            return false;
         }
         if (role.getContainer() instanceof ClientModel) {
             if (root.clients().canMapCompositeRoles((ClientModel)role.getContainer())) return true;
         }
         if (!isPermissionsEnabled(role)){
-            return canManage(role);
+            return false;
         }
 
         ResourceServer resourceServer = getResourceServer(role);
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapCompositePermissionName(role), resourceServer.getId());
         if (policy.getAssociatedPolicies().isEmpty()) {
-            return canManage(role);
+            return false;
         }
 
         Resource roleResource = resource(role);
@@ -248,20 +257,21 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
 
     @Override
     public boolean canMapClientScope(RoleModel role) {
+        if (root.clients().canManageClientsDefault()) return true;
         if (!root.isAdminSameRealm()) {
-            return root.clients().canManage();
+            return false;
         }
         if (role.getContainer() instanceof ClientModel) {
             if (root.clients().canMapClientScopeRoles((ClientModel)role.getContainer())) return true;
         }
         if (!isPermissionsEnabled(role)){
-            return root.clients().canManage();
+            return false;
         }
 
         ResourceServer resourceServer = getResourceServer(role);
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapClientScopePermissionName(role), resourceServer.getId());
         if (policy.getAssociatedPolicies().isEmpty()) {
-            return root.clients().canManage();
+            return false;
         }
 
         Resource roleResource = resource(role);
@@ -288,6 +298,16 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         return false;
     }
 
+    public boolean canManageDefault(RoleModel role) {
+        if (role.getContainer() instanceof RealmModel) {
+            return root.realm().canManageRealmDefault();
+        } else if (role.getContainer() instanceof ClientModel) {
+            ClientModel client = (ClientModel)role.getContainer();
+            return root.clients().canManageClientsDefault();
+        }
+        return false;
+    }
+
     @Override
     public void requireManage(RoleModel role) {
         if (!canManage(role)) {
@@ -375,25 +395,15 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         Resource resource =  authz.getStoreFactory().getResourceStore().create(getRoleResourceName(role), server, server.getClientId());
         resource.setType("Role");
         Scope mapRoleScope = getMapRoleScope(server);
-        Policy policy = manageUsersPolicy(server);
-        Policy mapRolePermission = Helper.addScopePermission(authz, server, getMapRolePermissionName(role), resource, mapRoleScope, policy);
+        Policy mapRolePermission = Helper.addEmptyScopePermission(authz, server, getMapRolePermissionName(role), resource, mapRoleScope);
         mapRolePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
 
         Scope mapClientScope = getMapClientScope(server);
-        RoleModel mngClients = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_CLIENTS);
-        Policy mngClientsPolicy = rolePolicy(server, mngClients);
-        Policy mapClientScopePermission = Helper.addScopePermission(authz, server, getMapClientScopePermissionName(role), resource, mapClientScope, mngClientsPolicy);
+        Policy mapClientScopePermission = Helper.addEmptyScopePermission(authz, server, getMapClientScopePermissionName(role), resource, mapClientScope);
         mapClientScopePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
 
         Scope mapCompositeScope = getMapCompositeScope(server);
-        if (role.getContainer() instanceof RealmModel) {
-            RoleModel mngRealm = root.getRealmManagementClient().getRole(AdminRoles.MANAGE_REALM);
-            policy = rolePolicy(server, mngRealm);
-        } else {
-            policy = mngClientsPolicy;
-
-        }
-        Policy mapCompositePermission = Helper.addScopePermission(authz, server, getMapCompositePermissionName(role), resource, mapCompositeScope, policy);
+        Policy mapCompositePermission = Helper.addEmptyScopePermission(authz, server, getMapCompositePermissionName(role), resource, mapCompositeScope);
         mapCompositePermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
         return resource;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
index 05ce719..74163d9 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin.permissions;
 
+import org.keycloak.authorization.model.Policy;
 import org.keycloak.models.UserModel;
 
 import java.util.Map;
@@ -25,7 +26,7 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public interface UserPermissionEvaluator {
-    boolean canManage();
+     boolean canManage();
 
     void requireManage();
 
@@ -51,4 +52,12 @@ public interface UserPermissionEvaluator {
     void requireImpersonate(UserModel user);
 
     Map<String, Boolean> getAccess(UserModel user);
+
+    boolean canMapRoles(UserModel user);
+
+    void requireMapRoles(UserModel user);
+
+    boolean canManageGroupMembership(UserModel user);
+
+    void requireManageGroupMembership(UserModel user);
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java
index b57b710..d4184ed 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionManagement.java
@@ -38,4 +38,10 @@ public interface UserPermissionManagement {
     Policy managePermission();
 
     Policy viewPermission();
+
+    Policy manageGroupMembershipPermission();
+
+    Policy mapRolesPermission();
+
+    Policy impersonatePermission();
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
index f8dd53b..6666a7e 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
@@ -45,6 +45,12 @@ import java.util.Set;
  */
 class UserPermissions implements UserPermissionEvaluator, UserPermissionManagement {
     private static final Logger logger = Logger.getLogger(UserPermissions.class);
+    public static final String MAP_ROLES_SCOPE="map-roles";
+    public static final String IMPERSONATE_SCOPE="impersonate";
+    public static final String MANAGE_GROUP_MEMBERSHIP_SCOPE="manage-group-membership";
+    public static final String MAP_ROLES_PERMISSION_USERS = "map-roles.permission.users";
+    public static final String IMPERSONATE_PERMISSION_USERS = "impersonate.permission.users";
+    public static final String MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS = "manage-group-membership.permission.users";
     public static final String MANAGE_PERMISSION_USERS = "manage.permission.users";
     public static final String VIEW_PERMISSION_USERS = "view.permission.users";
     public static final String USERS_RESOURCE = "Users";
@@ -67,6 +73,9 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         ResourceServer server = root.realmResourceServer();
         Scope manageScope = root.realmManageScope();
         Scope viewScope = root.realmViewScope();
+        Scope mapRolesScope = root.initializeRealmScope(MAP_ROLES_SCOPE);
+        Scope impersonateScope = root.initializeRealmScope(IMPERSONATE_SCOPE);
+        Scope manageGroupMembershipScope = root.initializeRealmScope(MANAGE_GROUP_MEMBERSHIP_SCOPE);
 
         Resource usersResource = authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
         if (usersResource == null) {
@@ -74,17 +83,30 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
             Set<Scope> scopeset = new HashSet<>();
             scopeset.add(manageScope);
             scopeset.add(viewScope);
+            scopeset.add(mapRolesScope);
+            scopeset.add(impersonateScope);
+            scopeset.add(manageGroupMembershipScope);
             usersResource.updateScopes(scopeset);
         }
         Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
         if (managePermission == null) {
-            Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
-            Helper.addScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope, manageUsersPolicy);
+            Helper.addEmptyScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope);
         }
         Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
         if (viewPermission == null) {
-            Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
-            Helper.addScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope, viewUsersPolicy);
+            Helper.addEmptyScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope);
+        }
+        Policy mapRolesPermission = authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
+        if (mapRolesPermission == null) {
+            Helper.addEmptyScopePermission(authz, server, MAP_ROLES_PERMISSION_USERS, usersResource, mapRolesScope);
+        }
+        Policy membershipPermission = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
+        if (membershipPermission == null) {
+            Helper.addEmptyScopePermission(authz, server, MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, usersResource, manageGroupMembershipScope);
+        }
+        Policy impersonatePermission = authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
+        if (impersonatePermission == null) {
+            Helper.addEmptyScopePermission(authz, server, IMPERSONATE_PERMISSION_USERS, usersResource, impersonateScope);
         }
     }
 
@@ -93,6 +115,9 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         Map<String, String> scopes = new HashMap<>();
         scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission().getId());
         scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission().getId());
+        scopes.put(MAP_ROLES_SCOPE, mapRolesPermission().getId());
+        scopes.put(MANAGE_GROUP_MEMBERSHIP_SCOPE, manageGroupMembershipPermission().getId());
+        scopes.put(IMPERSONATE_SCOPE, impersonatePermission().getId());
         return scopes;
     }
 
@@ -117,7 +142,22 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         } else {
             ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
             if (server == null) return;
-            Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
+            Policy policy = managePermission();
+            if (policy == null) {
+                authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+
+            }
+            policy = viewPermission();
+            if (policy == null) {
+                authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+
+            }
+            policy = mapRolesPermission();
+            if (policy == null) {
+                authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+
+            }
+            policy = manageGroupMembershipPermission();
             if (policy == null) {
                 authz.getStoreFactory().getPolicyStore().delete(policy.getId());
 
@@ -153,6 +193,25 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         return authz.getStoreFactory().getPolicyStore().findByName(VIEW_PERMISSION_USERS, server.getId());
     }
 
+    @Override
+    public Policy manageGroupMembershipPermission() {
+        ResourceServer server = root.realmResourceServer();
+        return authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
+    }
+
+    @Override
+    public Policy mapRolesPermission() {
+        ResourceServer server = root.realmResourceServer();
+        return authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
+    }
+
+
+    @Override
+    public Policy impersonatePermission() {
+        ResourceServer server = root.realmResourceServer();
+        return authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
+    }
+
 
 
     /**
@@ -170,25 +229,26 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
      */
     @Override
     public boolean canManage() {
+        if (canManageDefault()) return true;
         if (!root.isAdminSameRealm()) {
-            return canManageDefault();
+            return false;
         }
 
         ResourceServer server = root.realmResourceServer();
-        if (server == null) return canManageDefault();
+        if (server == null) return false;
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
-        if (resource == null) return canManageDefault();
+        if (resource == null) return false;
 
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_PERMISSION_USERS, server.getId());
         if (policy == null) {
-            return canManageDefault();
+            return false;
         }
 
         Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
         // if no policies attached to permission then just do default behavior
         if (associatedPolicies == null || associatedPolicies.isEmpty()) {
-            return canManageDefault();
+            return false;
         }
 
         Scope scope = root.realmManageScope();
@@ -321,14 +381,15 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
      */
     @Override
     public boolean canView() {
+        if (canViewDefault()) return true;
         if (!root.isAdminSameRealm()) {
-            return canViewDefault();
+            return false;
         }
 
         return hasViewPermission() || canManage();
     }
 
-    public boolean hasViewPermission() {
+    private boolean hasViewPermission() {
         ResourceServer server = root.realmResourceServer();
         if (server == null) return canViewDefault();
 
@@ -382,7 +443,32 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
 
     @Override
     public boolean canImpersonate(UserModel user) {
-        return root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE);
+        if (root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE)) return true;
+
+        if (!root.isAdminSameRealm()) {
+            return false;
+        }
+
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return false;
+
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+        if (resource == null) return false;
+
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(IMPERSONATE_PERMISSION_USERS, server.getId());
+        if (policy == null) {
+            return false;
+        }
+
+        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+        // if no policies attached to permission then just do default behavior
+        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+            return false;
+        }
+
+        Scope scope = root.realmScope(IMPERSONATE_SCOPE);
+        return root.evaluatePermission(resource, scope, server);
+
     }
 
     @Override
@@ -397,9 +483,90 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         Map<String, Boolean> map = new HashMap<>();
         map.put("view", canView(user));
         map.put("manage", canManage(user));
+        map.put("mapRoles", canMapRoles(user));
+        map.put("manageGroupMembership", canManageGroupMembership(user));
+        map.put("impersonate", canImpersonate(user));
         return map;
     }
 
+    @Override
+    public boolean canMapRoles(UserModel user) {
+        if (canManage(user)) return true;
+
+        if (!root.isAdminSameRealm()) {
+            return false;
+        }
+
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return false;
+
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+        if (resource == null) return false;
+
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MAP_ROLES_PERMISSION_USERS, server.getId());
+        if (policy == null) {
+            return false;
+        }
+
+        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+        // if no policies attached to permission then just do default behavior
+        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+            return false;
+        }
+
+        Scope scope = root.realmScope(MAP_ROLES_SCOPE);
+        return root.evaluatePermission(resource, scope, server);
+
+    }
+
+    @Override
+    public void requireMapRoles(UserModel user) {
+        if (!canMapRoles(user)) {
+            throw new ForbiddenException();
+        }
+
+    }
+
+
+    @Override
+    public boolean canManageGroupMembership(UserModel user) {
+        if (canManage(user)) return true;
+
+        if (!root.isAdminSameRealm()) {
+            return false;
+        }
+
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return false;
+
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(USERS_RESOURCE, server.getId());
+        if (resource == null) return false;
+
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, server.getId());
+        if (policy == null) {
+            return false;
+        }
+
+        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
+        // if no policies attached to permission then just do default behavior
+        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
+            return false;
+        }
+
+        Scope scope = root.realmScope(MANAGE_GROUP_MEMBERSHIP_SCOPE);
+        return root.evaluatePermission(resource, scope, server);
+
+    }
+
+    @Override
+    public void requireManageGroupMembership(UserModel user) {
+        if (!canManageGroupMembership(user)) {
+            throw new ForbiddenException();
+        }
+
+    }
+
+
 
 
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 9e0a89e..b00f2e4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -96,18 +96,11 @@ public class RealmsAdminResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<RealmRepresentation> getRealms() {
-        RealmManager realmManager = new RealmManager(session);
         List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
-        if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            List<RealmModel> realms = session.realms().getRealms();
-            for (RealmModel realm : realms) {
-                addRealmRep(reps, realm, realm.getMasterAdminClient());
-            }
-        } else {
-            ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
-            addRealmRep(reps, auth.getRealm(), adminApp);
+        List<RealmModel> realms = session.realms().getRealms();
+        for (RealmModel realm : realms) {
+            addRealmRep(reps, realm);
         }
-
         if (reps.isEmpty()) {
             throw new ForbiddenException();
         }
@@ -116,10 +109,10 @@ public class RealmsAdminResource {
         return reps;
     }
 
-    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ClientModel realmManagementClient) {
-        if (auth.hasAppRole(realmManagementClient, AdminRoles.VIEW_REALM)) {
+    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm) {
+        if (AdminPermissions.realms(session, auth).canView(realm)) {
             reps.add(ModelToRepresentation.toRepresentation(realm, false));
-        } else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) {
+        } else if (AdminPermissions.realms(session, auth).isAdmin(realm)) {
             RealmRepresentation rep = new RealmRepresentation();
             rep.setRealm(realm.getName());
             reps.add(rep);
@@ -140,12 +133,7 @@ public class RealmsAdminResource {
     public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
         RealmManager realmManager = new RealmManager(session);
         realmManager.setContextPath(keycloak.getContextPath());
-        if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            throw new ForbiddenException();
-        }
-        if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
-            throw new ForbiddenException();
-        }
+        AdminPermissions.realms(session, auth).requireCreateRealm();
 
         logger.debugv("importRealm: {0}", rep.getRealm());
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
index 8db0591..b785b1a 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
@@ -232,7 +232,7 @@ public class RoleMapperResource {
             if (roleModel == null || !roleModel.getId().equals(role.getId())) {
                 throw new NotFoundException("Role not found");
             }
-            checkMapRolePermission(roleModel);
+            auth.roles().requireMapRole(roleModel);
             roleMapper.grantRole(roleModel);
         }
 
@@ -256,7 +256,7 @@ public class RoleMapperResource {
             roles = new LinkedList<>();
 
             for (RoleModel roleModel : roleModels) {
-                checkMapRolePermission(roleModel);
+                auth.roles().requireMapRole(roleModel);
                 roleMapper.deleteRoleMapping(roleModel);
                 roles.add(ModelToRepresentation.toRepresentation(roleModel));
             }
@@ -267,7 +267,7 @@ public class RoleMapperResource {
                 if (roleModel == null || !roleModel.getId().equals(role.getId())) {
                     throw new NotFoundException("Role not found");
                 }
-                checkMapRolePermission(roleModel);
+                auth.roles().requireMapRole(roleModel);
                 try {
                     roleMapper.deleteRoleMapping(roleModel);
                 } catch (ModelException me) {
@@ -283,12 +283,6 @@ public class RoleMapperResource {
 
     }
 
-    private void checkMapRolePermission(RoleModel roleModel) {
-        if (!canMapRole(roleModel)) {
-            throw new ForbiddenException();
-        }
-    }
-
     private boolean canMapRole(RoleModel roleModel) {
         return auth.roles().canMapRole(roleModel);
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
index cdd9cd7..0161ee6 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
@@ -67,7 +67,7 @@ public abstract class RoleResource {
             if (composite == null) {
                 throw new NotFoundException("Could not find composite role");
             }
-            auth.roles().requireManage(composite);
+            auth.roles().requireMapComposite(composite);
             role.addCompositeRole(composite);
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
index ca9d536..bf3b236 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
@@ -534,7 +534,7 @@ public class UserResource {
 
     @Path("role-mappings")
     public RoleMapperResource getRoleMappings() {
-        AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.users().requireManage(user);
+        AdminPermissionEvaluator.RequirePermissionCheck manageCheck = () -> auth.users().requireMapRoles(user);
         AdminPermissionEvaluator.RequirePermissionCheck viewCheck = () -> auth.users().requireView(user);
         RoleMapperResource resource =  new RoleMapperResource(realm, auth, user, adminEvent, manageCheck, viewCheck);
         ResteasyProviderFactory.getInstance().injectProperties(resource);
@@ -756,13 +756,13 @@ public class UserResource {
     @Path("groups/{groupId}")
     @NoCache
     public void removeMembership(@PathParam("groupId") String groupId) {
-        auth.users().requireManage(user);
+        auth.users().requireManageGroupMembership(user);
 
         GroupModel group = session.realms().getGroupById(groupId, realm);
         if (group == null) {
             throw new NotFoundException("Group not found");
         }
-        auth.groups().requireManageMembers(group);
+        auth.groups().requireManageMembership(group);
 
         try {
             if (user.isMemberOf(group)){
@@ -780,12 +780,12 @@ public class UserResource {
     @Path("groups/{groupId}")
     @NoCache
     public void joinGroup(@PathParam("groupId") String groupId) {
-        auth.users().requireManage(user);
+        auth.users().requireManageGroupMembership(user);
         GroupModel group = session.realms().getGroupById(groupId, realm);
         if (group == null) {
             throw new NotFoundException("Group not found");
         }
-        //auth.groups().requireManageMembers(group);
+        auth.groups().requireManageMembership(group);
         if (!user.isMemberOf(group)){
             user.joinGroup(group);
             adminEvent.operation(OperationType.CREATE).resource(ResourceType.GROUP_MEMBERSHIP).representation(ModelToRepresentation.toRepresentation(group, true)).resourcePath(uriInfo).success();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
index d32ad79..37d3a96 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
@@ -66,6 +66,43 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
         testRealmRep.setEnabled(true);
         testRealms.add(testRealmRep);
     }
+    public static void setupDemo(KeycloakSession session) {
+        RealmModel realm = session.realms().getRealmByName(TEST);
+        ClientModel client = realm.addClient("sales-pipeline-application");
+        RoleModel clientAdmin = client.addRole("admin");
+        client.addRole("leader-creator");
+        client.addRole("viewLeads");
+        ClientModel client2 = realm.addClient("market-analysis-application");
+        RoleModel client2Admin = client2.addRole("admin");
+        client2.addRole("market-manager");
+        client2.addRole("viewMarkets");
+        GroupModel sales = realm.createGroup("sales");
+        RoleModel salesAppsAdminRole = realm.addRole("sales-apps-admin");
+        salesAppsAdminRole.addCompositeRole(clientAdmin);
+        salesAppsAdminRole.addCompositeRole(client2Admin);
+
+
+        UserModel admin = session.users().addUser(realm, "salesManager");
+        admin.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
+        admin = session.users().addUser(realm, "sales-group-admin");
+        admin.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
+        admin = session.users().addUser(realm, "sales-it");
+        admin.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
+        admin = session.users().addUser(realm, "sales-pipeline-admin");
+        admin.setEnabled(true);
+        session.userCredentialManager().updateCredential(realm, admin, UserCredentialModel.password("password"));
+
+        UserModel user = session.users().addUser(realm, "salesman");
+        user.setEnabled(true);
+        user.joinGroup(sales);
+
+        user = session.users().addUser(realm, "saleswoman");
+        user.setEnabled(true);
+
+    }
 
     public static void setupPolices(KeycloakSession session) {
         RealmModel realm = session.realms().getRealmByName(TEST);
@@ -304,9 +341,14 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
     protected boolean isImportAfterEachMethod() {
         return true;
     }
+    //@Test
+    public void testDemo() throws Exception {
+        testingClient.server().run(FineGrainAdminUnitTest::setupDemo);
+        Thread.sleep(1000000000);
+    }
 
 
-    @Test
+    //@Test
     public void testUI() throws Exception {
         testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
         testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
index 4b0de12..16b0804 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/PermissionsTest.java
@@ -717,7 +717,7 @@ public class PermissionsTest extends AbstractKeycloakTest {
             public void invoke(RealmResource realm) {
                 realm.clientTemplates().findAll();
             }
-        }, Resource.CLIENT, false);
+        }, Resource.CLIENT, false, true);
         invoke(new InvocationWithResponse() {
             public void invoke(RealmResource realm, AtomicReference<Response> response) {
                 ClientTemplateRepresentation template = new ClientTemplateRepresentation();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
index 9c9bfc2..5fbec89 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
@@ -29,7 +29,7 @@ log4j.appender.testsuite.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%C{1}] 
 keycloak.logging.level=info
 log4j.logger.org.keycloak=${keycloak.logging.level}
 
-log4j.logger.org.jboss.resteasy.resteasy_jaxrs.i18n=off
+#log4j.logger.org.jboss.resteasy.resteasy_jaxrs.i18n=off
 
 #log4j.logger.org.keycloak.keys.DefaultKeyManager=trace
 #log4j.logger.org.keycloak.services.managers.AuthenticationManager=trace
@@ -62,7 +62,7 @@ log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=de
 
 log4j.logger.org.xnio=off
 log4j.logger.org.hibernate=off
-log4j.logger.org.jboss.resteasy=warn
+log4j.logger.org.jboss.resteasy=info
 log4j.logger.org.apache.directory.api=warn
 log4j.logger.org.apache.directory.server.core=warn
 
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 37b4984..6834ac8 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
@@ -2394,6 +2394,7 @@ module.controller('ClientRolePermissionsCtrl', function($scope, $http, $route, $
         $scope.permissions = data;
     });
     $scope.setEnabled = function() {
+        console.log('perssions enabled: ' + $scope.permissions.enabled);
         var param = { enabled: $scope.permissions.enabled};
         $scope.permissions = RoleManagementPermissions.update({realm: realm.realm, role:role.id}, param);
     };
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/group-attributes.html b/themes/src/main/resources/theme/base/admin/resources/partials/group-attributes.html
index c3962c5..e12c553 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/group-attributes.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/group-attributes.html
@@ -6,7 +6,7 @@
 
     <kc-tabs-group></kc-tabs-group>
 
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageUsers">
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!group.access.manage">
         <table class="table table-striped table-bordered">
             <thead>
             <tr>
@@ -29,7 +29,7 @@
             </tbody>
         </table>
 
-        <div class="form-group" data-ng-show="access.manageUsers">
+        <div class="form-group" data-ng-show="group.access.manage">
             <div class="col-md-12">
                 <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/group-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/group-detail.html
index 677ea32..8fd6461 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/group-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/group-detail.html
@@ -16,7 +16,7 @@
             </div>
         </fieldset>
 
-        <div class="form-group" data-ng-show="access.manageUsers">
+        <div class="form-group" data-ng-show="group.access.manage">
             <div class="col-md-10 col-md-offset-2">
                 <button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html b/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
index 9a1c5b8..62aa7d4 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
@@ -7,7 +7,7 @@
     <kc-tabs-group></kc-tabs-group>
 
     <form class="form-horizontal" name="realmForm" novalidate>
-        <div class="form-group" kc-read-only="!access.manageUsers">
+        <div class="form-group" kc-read-only="!group.access.manage">
             <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
 
             <div class="col-md-10">
@@ -54,7 +54,7 @@
                     <span>{{:: 'client-roles' | translate}}</span>
                     <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select>
                 </label>
-                <div class="col-md-10" kc-read-only="!access.manageUsers">
+                <div class="col-md-10" kc-read-only="!group.access.manage">
                     <div class="row" data-ng-hide="targetClient">
                         <div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div>
                     </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
index b57b1d2..013dae7 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
@@ -7,7 +7,7 @@
     <kc-tabs-user></kc-tabs-user>
 
     <form class="form-horizontal" name="realmForm" novalidate>
-        <div class="form-group" kc-read-only="!access.manageUsers">
+        <div class="form-group" kc-read-only="!user.access.mapRoles">
             <label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
 
             <div class="col-md-10">
@@ -54,7 +54,7 @@
                     <span>{{:: 'client-roles' | translate}}</span>
                     <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="targetClient" ng-options="a.clientId for a in clients | orderBy:'clientId'" ng-disabled="false"></select>
                 </label>
-                <div class="col-md-10" kc-read-only="!access.manageUsers">
+                <div class="col-md-10" kc-read-only="!user.access.mapRoles">
                     <div class="row" data-ng-hide="targetClient">
                         <div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div>
                     </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
index d7259fd..88e66e7 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
@@ -138,7 +138,7 @@
                 <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
             </div>
 
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && !user.access.manage">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && user.access.manage">
                 <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
             </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-group-membership.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-group-membership.html
index a9c0e6d..f7bf04e 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-group-membership.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-group-membership.html
@@ -7,7 +7,7 @@
      <kc-tabs-user></kc-tabs-user>
 
      <form class="form-horizontal" name="realmForm" novalidate>
-         <div class="form-group" kc-read-only="!access.manageUsers">
+         <div class="form-group" kc-read-only="!user.access.manageGroupMembership">
              <label class="col-md-1 control-label" class="control-label"></label>
 
              <div class="col-md-8" >
@@ -21,7 +21,7 @@
                                          <label class="control-label">{{:: 'group-membership' | translate}}</label>
                                          <kc-tooltip>{{:: 'group-membership.tooltip' | translate}}</kc-tooltip>
 
-                                         <div class="pull-right" data-ng-show="access.manageUsers">
+                                         <div class="pull-right" data-ng-show="user.access.manageGroupMembership">
                                              <button id="leaveGroups" class="btn btn-default" ng-click="leaveGroup()">{{:: 'leave' | translate}}</button>
                                          </div>
                                      </div>
@@ -53,7 +53,7 @@
                                          <label class="control-label">{{:: 'available-groups' | translate}}</label>
                                          <kc-tooltip>{{:: 'membership.available-groups.tooltip' | translate}}</kc-tooltip>
 
-                                         <div class="pull-right" data-ng-show="access.manageUsers">
+                                         <div class="pull-right" data-ng-show="user.access.manageGroupMembership">
                                              <button id="joinGroup" class="btn btn-default" ng-click="joinGroup()">{{:: 'join' | translate}}</button>
                                          </div>
                                      </div>