keycloak-aplcache

ui for permission reference

6/5/2017 8:52:51 PM

Changes

Details

diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index 58ae623..36362cb 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -31,6 +31,7 @@ import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
@@ -41,6 +42,7 @@ import org.keycloak.protocol.ClientInstallationProvider;
 import org.keycloak.representations.adapters.action.GlobalRequestResult;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.ManagementPermissionReference;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.representations.idm.UserSessionRepresentation;
 import org.keycloak.services.ErrorResponse;
@@ -52,6 +54,8 @@ import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.KeycloakApplication;
 import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
 import org.keycloak.services.validation.ClientValidator;
 import org.keycloak.services.validation.PairwiseClientValidator;
 import org.keycloak.services.validation.ValidationMessages;
@@ -536,4 +540,55 @@ public class ClientResource {
 
         return resource;
     }
+
+    /**
+     * Return object stating whether client Authorization permissions have been initialized or not and a reference
+     *
+     * @return
+     */
+    @Path("management/permissions")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public ManagementPermissionReference getManagementPermissions() {
+        auth.roles().requireView(client);
+
+        AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
+        if (!permissions.clients().isPermissionsEnabled(client)) {
+            return new ManagementPermissionReference();
+        }
+        return toMgmtRef(client, permissions);
+    }
+
+    public static ManagementPermissionReference toMgmtRef(ClientModel client, AdminPermissionManagement permissions) {
+        ManagementPermissionReference ref = new ManagementPermissionReference();
+        ref.setEnabled(true);
+        ref.setResource(permissions.clients().resource(client).getId());
+        ref.setScopePermissions(permissions.clients().getPermissions(client));
+        return ref;
+    }
+
+
+    /**
+     * Return object stating whether client Authorization permissions have been initialized or not and a reference
+     *
+     *
+     * @return initialized manage permissions reference
+     */
+    @Path("management/permissions")
+    @PUT
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @NoCache
+    public ManagementPermissionReference setManagementPermissionsEnabled(ManagementPermissionReference ref) {
+        auth.clients().requireManage(client);
+         if (ref.isEnabled()) {
+            AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
+            permissions.clients().setPermissionsEnabled(client, ref.isEnabled());
+            return toMgmtRef(client, permissions);
+        } else {
+            return new ManagementPermissionReference();
+        }
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index d620560..41b91be 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -207,7 +207,7 @@ public class ClientsResource {
         ClientModel clientModel = realm.getClientById(id);
         if (clientModel == null) {
             // we do this to make sure somebody can't phish ids
-            if (!auth.clients().canList()) throw new NotFoundException("Could not find client");
+            if (auth.clients().canList()) throw new NotFoundException("Could not find client");
             else throw new ForbiddenException();
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
index a529a48..a5b7a6c 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupResource.java
@@ -21,6 +21,7 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.GroupModel;
 import org.keycloak.models.KeycloakSession;
@@ -28,6 +29,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.ManagementPermissionReference;
 import org.keycloak.representations.idm.UserRepresentation;
 
 import javax.ws.rs.Consumes;
@@ -50,6 +52,8 @@ import java.util.Map;
 import java.util.Set;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
+import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
+import org.keycloak.services.resources.admin.permissions.AdminPermissions;
 
 /**
  * @resource Groups
@@ -214,4 +218,55 @@ public class GroupResource {
         return results;
     }
 
+    /**
+     * Return object stating whether client Authorization permissions have been initialized or not and a reference
+     *
+     * @return
+     */
+    @Path("management/permissions")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @NoCache
+    public ManagementPermissionReference getManagementPermissions() {
+        auth.groups().requireView(group);
+
+        AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
+        if (!permissions.groups().isPermissionsEnabled(group)) {
+            return new ManagementPermissionReference();
+        }
+        return toMgmtRef(group, permissions);
+    }
+
+    public static ManagementPermissionReference toMgmtRef(GroupModel group, AdminPermissionManagement permissions) {
+        ManagementPermissionReference ref = new ManagementPermissionReference();
+        ref.setEnabled(true);
+        ref.setResource(permissions.groups().resource(group).getId());
+        ref.setScopePermissions(permissions.groups().getPermissions(group));
+        return ref;
+    }
+
+
+    /**
+     * Return object stating whether client Authorization permissions have been initialized or not and a reference
+     *
+     *
+     * @return initialized manage permissions reference
+     */
+    @Path("management/permissions")
+    @PUT
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @NoCache
+    public ManagementPermissionReference setManagementPermissionsEnabled(ManagementPermissionReference ref) {
+        auth.groups().requireManage(group);
+        if (ref.isEnabled()) {
+            AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
+            permissions.groups().setPermissionsEnabled(group, ref.isEnabled());
+            return toMgmtRef(group, permissions);
+        } else {
+            return new ManagementPermissionReference();
+        }
+    }
+
 }
+
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java
index 26ae951..d967443 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionManagement.java
@@ -17,21 +17,38 @@
 package org.keycloak.services.resources.admin.permissions;
 
 import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.models.ClientModel;
 
+import java.util.Map;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public interface ClientPermissionManagement {
     public static final String MAP_ROLES_SCOPE = "map-roles";
+    public static final String MAP_ROLES_CLIENT_SCOPE = "map-roles-client-scope";
+    public static final String MAP_ROLES_COMPOSITE_SCOPE = "map-roles-composite";
 
     boolean isPermissionsEnabled(ClientModel client);
 
     void setPermissionsEnabled(ClientModel client, boolean enable);
 
+    Resource resource(ClientModel client);
+
+    Map<String, String> getPermissions(ClientModel client);
+
     Policy mapRolesPermission(ClientModel client);
 
+    Policy mapRolesClientScopePermission(ClientModel client);
+
+    Policy mapRolesCompositePermission(ClientModel client);
+
+    Policy managePermission(ClientModel client);
+
+    Policy viewPermission(ClientModel client);
+
     ResourceServer resourceServer(ClientModel client);
 }
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 3118f7a..06fa5d8 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
@@ -30,7 +30,9 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.services.ForbiddenException;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -67,11 +69,11 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     private String getMapRolesPermissionName(ClientModel client) {
         return MAP_ROLES_SCOPE + ".permission.client." + client.getId();
     }
-    private String getMapRoleClientScopePermissionName(ClientModel client) {
-        return RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE + ".permission.client." + client.getId();
+    private String getMapRolesClientScopePermissionName(ClientModel client) {
+        return MAP_ROLES_CLIENT_SCOPE + ".permission.client." + client.getId();
     }
-    private String getMapRoleCompositePermissionName(ClientModel client) {
-        return RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE + ".permission.client." + client.getId();
+    private String getMapRolesCompositePermissionName(ClientModel client) {
+        return MAP_ROLES_COMPOSITE_SCOPE + ".permission.client." + client.getId();
     }
 
     private void initialize(ClientModel client) {
@@ -88,13 +90,13 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         if (mapRoleScope == null) {
             mapRoleScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_SCOPE, server);
         }
-        Scope mapRoleClientScope = mapRoleClientScope(server);
+        Scope mapRoleClientScope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_CLIENT_SCOPE, server.getId());
         if (mapRoleClientScope == null) {
-            mapRoleClientScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, server);
+            mapRoleClientScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_CLIENT_SCOPE, server);
         }
-        Scope mapRoleCompositeScope = mapRoleCompositeScope(server);
+        Scope mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_COMPOSITE_SCOPE, server.getId());
         if (mapRoleCompositeScope == null) {
-            mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, server);
+            mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_COMPOSITE_SCOPE, server);
         }
 
         String resourceName = getResourceName(client);
@@ -129,12 +131,12 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         if (mapRolePermission == null) {
             Helper.addEmptyScopePermission(authz, server, mapRolePermissionName, resource, mapRoleScope);
         }
-        String mapRoleClientScopePermissionName = getMapRoleClientScopePermissionName(client);
+        String mapRoleClientScopePermissionName = getMapRolesClientScopePermissionName(client);
         Policy mapRoleClientScopePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleClientScopePermissionName, server.getId());
         if (mapRoleClientScopePermission == null) {
             Helper.addEmptyScopePermission(authz, server, mapRoleClientScopePermissionName, resource, mapRoleClientScope);
         }
-        String mapRoleCompositePermissionName = getMapRoleCompositePermissionName(client);
+        String mapRoleCompositePermissionName = getMapRolesCompositePermissionName(client);
         Policy mapRoleCompositePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleCompositePermissionName, server.getId());
         if (mapRoleCompositePermission == null) {
             Helper.addEmptyScopePermission(authz, server, mapRoleCompositePermissionName, resource, mapRoleCompositeScope);
@@ -155,8 +157,8 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         deletePolicy(getManagePermissionName(client), client, server);
         deletePolicy(getViewPermissionName(client), client, server);
         deletePolicy(getMapRolesPermissionName(client), client, server);
-        deletePolicy(getMapRoleClientScopePermissionName(client), client, server);
-        deletePolicy(getMapRoleCompositePermissionName(client), client, server);
+        deletePolicy(getMapRolesClientScopePermissionName(client), client, server);
+        deletePolicy(getMapRolesCompositePermissionName(client), client, server);
         Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
         if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
     }
@@ -190,12 +192,6 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     private Scope mapRolesScope(ResourceServer server) {
         return authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_SCOPE, server.getId());
     }
-    private Scope mapRoleClientScope(ResourceServer server) {
-        return authz.getStoreFactory().getScopeStore().findByName(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, server.getId());
-    }
-    private Scope mapRoleCompositeScope(ResourceServer server) {
-        return authz.getStoreFactory().getScopeStore().findByName(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, server.getId());
-    }
 
     @Override
     public boolean canList() {
@@ -251,6 +247,27 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     }
 
     @Override
+    public Resource resource(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
+        if (resource == null) return null;
+        return resource;
+    }
+
+    @Override
+    public Map<String, String> getPermissions(ClientModel client) {
+        Map<String, String> scopes = new HashMap<>();
+        scopes.put(MAP_ROLES_SCOPE,  mapRolesPermission(client).getId());
+        scopes.put(MAP_ROLES_CLIENT_SCOPE, mapRolesClientScopePermission(client).getId());
+        scopes.put(MAP_ROLES_COMPOSITE_SCOPE, mapRolesCompositePermission(client).getId());
+        scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(client).getId());
+        scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(client).getId());
+        return scopes;
+    }
+
+
+    @Override
     public boolean canManage(ClientModel client) {
         if (!root.isAdminSameRealm()) {
             return canManage();
@@ -398,6 +415,34 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     }
 
     @Override
+    public Policy mapRolesClientScopePermission(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesClientScopePermissionName(client), server.getId());
+    }
+
+    @Override
+    public Policy mapRolesCompositePermission(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesCompositePermissionName(client), server.getId());
+    }
+
+    @Override
+    public Policy managePermission(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        return authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
+    }
+
+    @Override
+    public Policy viewPermission(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        return authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
+    }
+
+    @Override
     public ResourceServer resourceServer(ClientModel client) {
         return authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
     }
@@ -410,7 +455,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
         if (resource == null) return false;
 
-        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRoleCompositePermissionName(client), server.getId());
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolesCompositePermissionName(client), server.getId());
         if (policy == null) {
             return false;
         }
@@ -421,7 +466,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             return false;
         }
 
-        Scope scope = mapRoleCompositeScope(server);
+        Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_COMPOSITE_SCOPE, server.getId());
         return root.evaluatePermission(resource, scope, server);
     }
     @Override
@@ -432,7 +477,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
         if (resource == null) return false;
 
-        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRoleClientScopePermissionName(client), server.getId());
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolesClientScopePermissionName(client), server.getId());
         if (policy == null) {
             return false;
         }
@@ -443,7 +488,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             return false;
         }
 
-        Scope scope = mapRoleClientScope(server);
+        Scope scope = authz.getStoreFactory().getScopeStore().findByName(MAP_ROLES_CLIENT_SCOPE, server.getId());
         return root.evaluatePermission(resource, scope, server);
     }
 
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 5f4097b..a3277ba 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
@@ -17,6 +17,7 @@
 package org.keycloak.services.resources.admin.permissions;
 
 import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.Resource;
 import org.keycloak.models.GroupModel;
 import org.keycloak.models.RoleModel;
 
@@ -34,4 +35,8 @@ public interface GroupPermissionManagement {
     Policy manageMembersPermission(GroupModel group);
     Policy viewPermissionGroup(GroupModel group);
     Policy managePermissionGroup(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 e1c0356..acf80c1 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
@@ -23,13 +23,16 @@ import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
 import org.keycloak.models.AdminRoles;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.GroupModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.services.ForbiddenException;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -54,16 +57,16 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
 
     private static String getGroupResourceName(GroupModel group) {
-        return "group.resource." + getGroupSuffix(group);
+        return "group.resource." + group.getId();
     }
 
 
     public static String getManagePermissionGroup(GroupModel group) {
-        return "manage.permission.group." + getGroupSuffix(group);
+        return "manage.permission.group." + group.getId();
     }
 
     public static String getManageMembersPermissionGroup(GroupModel group) {
-        return "manage.members.permission.group." + getGroupSuffix(group);
+        return "manage.members.permission.group." + group.getId();
     }
 
     public static String getGroupSuffix(GroupModel group) {
@@ -71,11 +74,11 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
     }
 
     public static String getViewPermissionGroup(GroupModel group) {
-        return "view.permission.group." + getGroupSuffix(group);
+        return "view.permission.group." + group.getId();
     }
 
     public static String getViewMembersPermissionGroup(GroupModel group) {
-        return "view.members.permission.group." + getGroupSuffix(group);
+        return "view.members.permission.group." + group.getId();
     }
 
     private void initialize(GroupModel group) {
@@ -102,7 +105,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
             Policy manageUsersPolicy = root.roles().manageUsersPolicy(server);
             Helper.addScopePermission(authz, server, managePermissionName, groupResource, manageScope, manageUsersPolicy);
         }
-        String viewPermissionName = getManagePermissionGroup(group);
+        String viewPermissionName = getViewPermissionGroup(group);
         Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(viewPermissionName, server.getId());
         if (viewPermission == null) {
             Policy viewUsersPolicy = root.roles().viewUsersPolicy(server);
@@ -213,6 +216,27 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
         return authz.getStoreFactory().getPolicyStore().findByName(managePermissionName, server.getId());
     }
 
+    @Override
+    public Resource resource(GroupModel group) {
+        ResourceServer server = root.realmResourceServer();
+        if (server == null) return null;
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getGroupResourceName(group), server.getId());
+        if (resource == null) return null;
+        return resource;
+    }
+
+    @Override
+    public Map<String, String> getPermissions(GroupModel group) {
+        Map<String, String> scopes = new HashMap<>();
+        scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermissionGroup(group).getId());
+        scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermissionGroup(group).getId());
+        scopes.put(MANAGE_MEMBERS_SCOPE, manageMembersPermission(group).getId());
+        scopes.put(VIEW_MEMBERS_SCOPE, viewMembersPermission(group).getId());
+        return scopes;
+    }
+
+
+
 
     @Override
     public boolean canManage(GroupModel group) {
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 5f666c6..83838de 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
@@ -141,19 +141,19 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
     @Override
     public boolean canMapRole(RoleModel role) {
         if (!root.isAdminSameRealm()) {
-            return root.users().canManage();
+            return root.users().canManageDefault();
         }
         if (role.getContainer() instanceof ClientModel) {
             if (root.clients().canMapRoles((ClientModel)role.getContainer())) return true;
         }
         if (!isPermissionsEnabled(role)){
-            return root.users().canManage();
+            return root.users().canManageDefault();
         }
 
         ResourceServer resourceServer = getResourceServer(role);
         Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolePermissionName(role), resourceServer.getId());
         if (policy.getAssociatedPolicies().isEmpty()) {
-            return root.users().canManage(); // if no policies applied, just do default
+            return root.users().canManageDefault(); // if no policies applied, just do default
         }
 
         Resource roleResource = resource(role);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
index 1601189..d6d2ad8 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
@@ -175,7 +175,11 @@ public abstract class AbstractKeycloakTest {
 
             // Cleanup objects
             for (TestCleanup cleanup : testContext.getCleanups().values()) {
-                if (cleanup != null) cleanup.executeCleanup();
+                try {
+                    if (cleanup != null) cleanup.executeCleanup();
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
             }
             testContext.getCleanups().clear();
         }
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 5d413d0..72f3df9 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
@@ -282,7 +282,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
     }
 
 
-    //@Test
+    @Test
     public void testUI() throws Exception {
         testingClient.server().run(FineGrainAdminUnitTest::setupPolices);
         testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
@@ -308,7 +308,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
         realmRoleSet.add(realmRole);
         RoleRepresentation realmRole2 = adminClient.realm(TEST).roles().get("realm-role2").toRepresentation();
         List<RoleRepresentation> realmRole2Set = new LinkedList<>();
-        realmRole2Set.add(realmRole);
+        realmRole2Set.add(realmRole2);
         ClientRepresentation client = adminClient.realm(TEST).clients().findByClientId("role-namespace").get(0);
         RoleRepresentation clientRole = adminClient.realm(TEST).clients().get(client.getId()).roles().get("client-role").toRepresentation();
         List<RoleRepresentation> clientRoleSet = new LinkedList<>();
@@ -395,18 +395,18 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
                     TEST, "groupManager", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
             List<RoleRepresentation> roles = null;
             realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
-            roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
+            roles = realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).listAll();
             Assert.assertTrue(roles.stream().anyMatch((r) -> {
                 return r.getName().equals("client-role");
             }));
-            realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).remove(clientRoleSet);
+            realmClient.realm(TEST).users().get(groupMember.getId()).roles().clientLevel(client.getId()).remove(clientRoleSet);
 
-            roles = realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().listAvailable();
+            roles = realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().listAvailable();
             Assert.assertEquals(roles.size(), 1);
-            realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRoleSet);
-            realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().remove(realmRoleSet);
+            realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().add(realmRoleSet);
+            realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().remove(realmRoleSet);
             try {
-                realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRole2Set);
+                realmClient.realm(TEST).users().get(groupMember.getId()).roles().realmLevel().add(realmRole2Set);
                 Assert.fail("should fail with forbidden exception");
             } catch (ClientErrorException e) {
                 Assert.assertEquals(e.getResponse().getStatus(), 403);
@@ -428,6 +428,8 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
             Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
                     TEST, "clientMapper", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
             List<RoleRepresentation> roles = null;
+            roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
+            Assert.assertTrue(roles.isEmpty());
             realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).add(clientRoleSet);
             roles = realmClient.realm(TEST).users().get(user1.getId()).roles().clientLevel(client.getId()).listAll();
             Assert.assertTrue(roles.stream().anyMatch((r) -> {
@@ -455,9 +457,6 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
         testingClient.server().run(FineGrainAdminUnitTest::setupUsers);
 
         UserRepresentation user1 = adminClient.realm(TEST).users().search("user1").get(0);
-        UserRepresentation user2 = adminClient.realm(TEST).users().search("user2").get(0);
-        UserRepresentation user3 = adminClient.realm(TEST).users().search("user3").get(0);
-        UserRepresentation user4 = adminClient.realm(TEST).users().search("user4").get(0);
         RoleRepresentation realmRole = adminClient.realm(TEST).roles().get("realm-role").toRepresentation();
         List<RoleRepresentation> realmRoleSet = new LinkedList<>();
         realmRoleSet.add(realmRole);
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 1dd53fa..11fe2c5 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -1306,7 +1306,8 @@ credential-reset-actions-timeout.tooltip=Maximum time before the action permit e
 ldap-mappers=LDAP Mappers
 create-ldap-mapper=Create LDAP mapper
 map-role-mgmt-scope-description=Policies that decide if an admin can map this role to a user or group
-manage-mgmt-scope-description=Policies that decide if an admin can manage this resource or resources
+manage-authz-users-scope-description=Policies that decide if an admin can manage all users in the realm
+view-authz-users-scope-description=Policies that decide if an admin can view all users in realm
 permissions-enabled-role=Permissions Enabled
 permissions-enabled-role.tooltip=Whether or not to enable fine grain permissions for managing this role.  Disabling will delete all current permissions that have been set up.
 manage-permissions-role.tooltip=Fine grain permissions for managing roles.  For example, you can define different policies for who is allowed to map a role.
@@ -1314,6 +1315,20 @@ lookup=Lookup
 manage-permissions-users.tooltip=Fine grain permssions for managing all users in realm.  You can define different policies for who is allowed to manage users in the realm.
 permissions-enabled-users=Permissions Enabled
 permissions-enabled-users.tooltip=Whether or not to enable fine grain permissions for managing users.  Disabling will delete all current permissions that have been set up.
+manage-permissions-client.tooltip=Fine grain permssions for admins that want to manage this client or apply roles defined by this client.
+manage-permissions-group.tooltip=Fine grain permssions for admins that want to manage this group or the members of this group.
+manage-authz-group-scope-description=Policies that decide if an admin can manage this group
+view-authz-group-scope-description=Policies that decide if an admin can view this group
+view.members-authz-group-scope-description=Policies that decide if an admin can manage the members of this group
+manage.members-authz-group-scope-description=Policies that decide if an admin can view the members of this group
+manage-authz-client-scope-description=Policies that decide if an admin can manage this client
+view-authz-client-scope-description=Policies that decide if an admin can view this client
+map-roles-authz-client-scope-description=Policies that decide if an admin can map roles defined by this client
+map-roles-client-scope-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client to the client scope of another client
+map-roles-composite-authz-client-scope-description=Policies that decide if an admin can apply roles defined by this client as a composite to another role
+map-role-authz-role-scope-description=Policies that decide if an admin can map role this role to a user or group
+map-role-client-scope-authz-role-scope-description=Policies that decide if an admin can apply this role to the client scope of a client
+map-role-composite-authz-role-scope-description=Policies that decide if an admin can apply this role as a composite to another role
 
 
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-app.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-app.js
index 455891d..047fa49 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-app.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-app.js
@@ -424,6 +424,30 @@ module.config(['$routeProvider', function ($routeProvider) {
         },
         controller : 'UsersPermissionsCtrl'
     })
+        .when('/realms/:realm/clients/:client/permissions', {
+            templateUrl : resourceUrl + '/partials/authz/mgmt/client-permissions.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                client : function(ClientLoader) {
+                    return ClientLoader();
+                }
+            },
+            controller : 'ClientPermissionsCtrl'
+        })
+        .when('/realms/:realm/groups/:group/permissions', {
+            templateUrl : resourceUrl + '/partials/authz/mgmt/group-permissions.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                group : function(GroupLoader) {
+                    return GroupLoader();
+                }
+            },
+            controller : 'GroupPermissionsCtrl'
+        })
     ;
 }]);
 
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 5eb0ba2..37b4984 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
@@ -2419,3 +2419,35 @@ module.controller('UsersPermissionsCtrl', function($scope, $http, $route, $locat
 
 });
 
+module.controller('ClientPermissionsCtrl', function($scope, $http, $route, $location, realm, client, ClientManagementPermissions, Notifications) {
+    $scope.client = client;
+    $scope.realm = realm;
+    ClientManagementPermissions.get({realm: realm.realm, client: client.id}, function(data) {
+        $scope.permissions = data;
+    });
+    $scope.setEnabled = function() {
+        var param = { enabled: $scope.permissions.enabled};
+        $scope.permissions = ClientManagementPermissions.update({realm: realm.realm, client: client.id}, param);
+    };
+
+
+});
+
+module.controller('GroupPermissionsCtrl', function($scope, $http, $route, $location, realm, group, GroupManagementPermissions, Client, Notifications) {
+    $scope.group = group;
+    $scope.realm = realm;
+    Client.query({realm: realm.realm, clientId: getManageClientId(realm)}, function(data) {
+        $scope.realmManagementClientId = data[0].id;
+    });
+    GroupManagementPermissions.get({realm: realm.realm, group: group.id}, function(data) {
+        $scope.permissions = data;
+    });
+    $scope.setEnabled = function() {
+        var param = { enabled: $scope.permissions.enabled};
+        $scope.permissions = GroupManagementPermissions.update({realm: realm.realm, group: group.id}, param);
+    };
+
+
+});
+
+
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 92219bb..f56ca8f 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
@@ -144,4 +144,50 @@ module.service('AuthzDialog', function($modal) {
     }
 
     return dialog;
-});
\ No newline at end of file
+});
+
+module.factory('RoleManagementPermissions', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/management/permissions', {
+        realm : '@realm',
+        role : '@role'
+    }, {
+        update: {
+            method: 'PUT'
+        }
+    });
+});
+
+module.factory('UsersManagementPermissions', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/users-management-permissions', {
+        realm : '@realm'
+    }, {
+        update: {
+            method: 'PUT'
+        }
+    });
+});
+
+module.factory('ClientManagementPermissions', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients/:client/management/permissions', {
+        realm : '@realm',
+        client : '@client'
+    }, {
+        update: {
+            method: 'PUT'
+        }
+    });
+});
+
+module.factory('GroupManagementPermissions', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/groups/:group/management/permissions', {
+        realm : '@realm',
+        group : '@group'
+    }, {
+        update: {
+            method: 'PUT'
+        }
+    });
+});
+
+
+
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js
index 50b50ab..e850b3b 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -842,28 +842,6 @@ module.factory('Role', function($resource) {
     });
 });
 
-module.factory('RoleManagementPermissions', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/management/permissions', {
-        realm : '@realm',
-        role : '@role'
-    }, {
-        update: {
-            method: 'PUT'
-        }
-    });
-});
-
-module.factory('UsersManagementPermissions', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/users-management-permissions', {
-        realm : '@realm'
-    }, {
-        update: {
-            method: 'PUT'
-        }
-    });
-});
-
-
 module.factory('RoleById', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role', {
         realm : '@realm',
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html
new file mode 100644
index 0000000..50241b2
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-permissions.html
@@ -0,0 +1,39 @@
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
+        <li>{{client.clientId}}</li>
+    </ol>
+
+    <kc-tabs-client></kc-tabs-client>
+
+    <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
+        <fieldset class="border-top">
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
+            <div class="col-md-6">
+                <input ng-model="permissions.enabled" ng-click="setEnabled()" name="permissionsEnabled" id="permissionsEnabled" ng-disabled="!access.manageAuthorization" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
+            </div>
+            <kc-tooltip>{{:: 'permissions-enabled-role.tooltip' | translate}}</kc-tooltip>
+        </div>
+        </fieldset>
+    </form>
+    <table class="datatable table table-striped table-bordered dataTable no-footer" data-ng-show="permissions.enabled">
+        <thead>
+        <tr>
+            <th>{{:: 'scope-name' | translate}}</th>
+            <th>{{:: 'description' | translate}}</th>
+            <th colspan="2">{{:: 'actions' | translate}}</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
+            <td translate="{{scopeName}}-authz-client-scope-description"></td>
+            <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
+        </tr>
+        </tbody>
+    </table>
+
+</div>
+
+<kc-menu></kc-menu>
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
index d2d6c14..988c1fa 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/client-role-permissions.html
@@ -2,7 +2,6 @@
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
         <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
-        <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">{{:: 'roles' | translate}}</a></li>
         <li>{{role.name}}</li>
     </ol>
 
@@ -30,7 +29,7 @@
         <tbody>
         <tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
             <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
-            <td translate="{{scopeName}}-mgmt-scope-description"></td>
+            <td translate="{{scopeName}}-authz-role-scope-description"></td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
         </tr>
         </tbody>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html
new file mode 100644
index 0000000..61770c9
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/group-permissions.html
@@ -0,0 +1,39 @@
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <ol class="breadcrumb">
+        <li><a href="#/realms/{{realm.realm}}/groups">{{:: 'groups' | translate}}</a></li>
+        <li>{{group.name}}</li>
+    </ol>
+
+    <kc-tabs-group></kc-tabs-group>
+
+    <form class=form-horizontal" name="enableForm" novalidate kc-read-only="!access.manageAuthorization">
+        <fieldset class="border-top">
+        <div class="form-group">
+            <label class="col-md-2 control-label" for="permissionsEnabled">{{:: 'permissions-enabled-role' | translate}}</label>
+            <div class="col-md-6">
+                <input ng-model="permissions.enabled" ng-click="setEnabled()" name="permissionsEnabled" id="permissionsEnabled" ng-disabled="!access.manageAuthorization" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
+            </div>
+            <kc-tooltip>{{:: 'permissions-enabled-role.tooltip' | translate}}</kc-tooltip>
+        </div>
+        </fieldset>
+    </form>
+    <table class="datatable table table-striped table-bordered dataTable no-footer" data-ng-show="permissions.enabled">
+        <thead>
+        <tr>
+            <th>{{:: 'scope-name' | translate}}</th>
+            <th>{{:: 'description' | translate}}</th>
+            <th colspan="2">{{:: 'actions' | translate}}</th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
+            <td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
+            <td translate="{{scopeName}}-authz-group-scope-description"></td>
+            <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
+        </tr>
+        </tbody>
+    </table>
+
+</div>
+
+<kc-menu></kc-menu>
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/realm-role-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/realm-role-permissions.html
index 82c8413..9c03333 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/realm-role-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/realm-role-permissions.html
@@ -28,7 +28,7 @@
         <tbody>
         <tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
             <td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
-            <td translate="{{scopeName}}-mgmt-scope-description"></td>
+            <td translate="{{scopeName}}-authz-role-scope-description"></td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
         </tr>
         </tbody>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/users-permissions.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/users-permissions.html
index 92a9067..4a5661f 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/users-permissions.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/mgmt/users-permissions.html
@@ -24,7 +24,7 @@
         <tbody>
         <tr ng-repeat="(scopeName, scopeId) in permissions.scopePermissions">
             <td><a href="#/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{scopeName}}</a></td>
-            <td translate="{{scopeName}}-mgmt-scope-description"></td>
+            <td translate="{{scopeName}}-authz-users-scope-description"></td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{realmManagementClientId}}/authz/resource-server/permission/scope/{{scopeId}}">{{:: 'edit' | translate}}</td>
         </tr>
         </tbody>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
index 2a3be32..a18c31f 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client.html
@@ -43,5 +43,9 @@
             <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/service-account-roles">{{:: 'service-account-roles' | translate}}</a>
             <kc-tooltip>{{:: 'service-account-roles.tooltip' | translate}}</kc-tooltip>
         </li>
+        <li ng-class="{active: path[4] == 'permissions'}">
+            <a href="#/realms/{{realm.realm}}/clients/{{client.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
+            <kc-tooltip>{{:: 'manage-permissions-client.tooltip' | translate}}</kc-tooltip>
+        </li>
     </ul>
 </div>
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group.html
index c242336..3aa12bc 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group.html
@@ -9,5 +9,9 @@
         <li ng-class="{active: path[4] == 'attributes'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/attributes">{{:: 'attributes' | translate}}</a></li>
         <li ng-class="{active: path[4] == 'role-mappings'}" ><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/role-mappings">{{:: 'role-mappings' | translate}}</a></li>
         <li ng-class="{active: path[4] == 'members'}"><a href="#/realms/{{realm.realm}}/groups/{{group.id}}/members">{{:: 'members' | translate}}</a></li>
+        <li ng-class="{active: path[4] == 'permissions'}">
+            <a href="#/realms/{{realm.realm}}/groups/{{group.id}}/permissions">{{:: 'authz-permissions' | translate}}</a>
+            <kc-tooltip>{{:: 'manage-permissions-group.tooltip' | translate}}</kc-tooltip>
+        </li>
     </ul>
 </div>
\ No newline at end of file