keycloak-aplcache

client permission tests

6/2/2017 4:49:20 PM

Details

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 5ff2e72..d620560 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
@@ -203,11 +203,12 @@ public class ClientsResource {
      */
     @Path("{id}")
     public ClientResource getClient(final @PathParam("id") String id) {
-        auth.clients().requireList();
 
         ClientModel clientModel = realm.getClientById(id);
         if (clientModel == null) {
-            throw new NotFoundException("Could not find client");
+            // we do this to make sure somebody can't phish ids
+            if (!auth.clients().canList()) throw new NotFoundException("Could not find client");
+            else throw new ForbiddenException();
         }
 
         session.getContext().setClient(clientModel);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
index 3da715a..51e26c0 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissionEvaluator.java
@@ -67,4 +67,10 @@ public interface ClientPermissionEvaluator {
     boolean canView(ClientTemplateModel template);
 
     void requireView(ClientTemplateModel template);
+
+    boolean canMapRoles(ClientModel client);
+
+    boolean canMapCompositeRoles(ClientModel client);
+
+    boolean canMapClientScopeRoles(ClientModel client);
 }
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 27f5527..26ae951 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
@@ -16,6 +16,8 @@
  */
 package org.keycloak.services.resources.admin.permissions;
 
+import org.keycloak.authorization.model.Policy;
+import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.models.ClientModel;
 
 /**
@@ -23,7 +25,13 @@ import org.keycloak.models.ClientModel;
  * @version $Revision: 1 $
  */
 public interface ClientPermissionManagement {
+    public static final String MAP_ROLES_SCOPE = "map-roles";
+
     boolean isPermissionsEnabled(ClientModel client);
 
     void setPermissionsEnabled(ClientModel client, boolean enable);
+
+    Policy mapRolesPermission(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 8209d2e..3118f7a 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
@@ -55,7 +55,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     }
 
     private String getResourceName(ClientModel client) {
-        return "group.resource." + client.getId();
+        return "client.resource." + client.getId();
     }
 
     private String getManagePermissionName(ClientModel client) {
@@ -64,25 +64,50 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     private String getViewPermissionName(ClientModel client) {
         return "view.permission.client." + client.getId();
     }
+    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 getMapRoleCompositePermissionName(ClientModel client) {
+        return RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE + ".permission.client." + client.getId();
+    }
 
     private void initialize(ClientModel client) {
         ResourceServer server = root.findOrCreateResourceServer(client);
         Scope manageScope = manageScope(server);
         if (manageScope == null) {
-            authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.MANAGE_SCOPE, server);
+            manageScope = authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.MANAGE_SCOPE, server);
         }
         Scope viewScope = viewScope(server);
-        if (manageScope == null) {
-            authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.VIEW_SCOPE, server);
+        if (viewScope == null) {
+            viewScope = authz.getStoreFactory().getScopeStore().create(AdminPermissionManagement.VIEW_SCOPE, server);
+        }
+        Scope mapRoleScope = mapRolesScope(server);
+        if (mapRoleScope == null) {
+            mapRoleScope = authz.getStoreFactory().getScopeStore().create(MAP_ROLES_SCOPE, server);
+        }
+        Scope mapRoleClientScope = mapRoleClientScope(server);
+        if (mapRoleClientScope == null) {
+            mapRoleClientScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_CLIENT_SCOPE_SCOPE, server);
+        }
+        Scope mapRoleCompositeScope = mapRoleCompositeScope(server);
+        if (mapRoleCompositeScope == null) {
+            mapRoleCompositeScope = authz.getStoreFactory().getScopeStore().create(RolePermissionManagement.MAP_ROLE_COMPOSITE_SCOPE, server);
         }
 
         String resourceName = getResourceName(client);
         Resource resource = authz.getStoreFactory().getResourceStore().findByName(resourceName, server.getId());
         if (resource == null) {
             resource = authz.getStoreFactory().getResourceStore().create(resourceName, server, server.getClientId());
+            resource.setType("Client");
             Set<Scope> scopeset = new HashSet<>();
             scopeset.add(manageScope);
             scopeset.add(viewScope);
+            scopeset.add(mapRoleScope);
+            scopeset.add(mapRoleClientScope);
+            scopeset.add(mapRoleCompositeScope);
             resource.updateScopes(scopeset);
         }
         String managePermissionName = getManagePermissionName(client);
@@ -99,26 +124,46 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             Policy viewClientsPolicy = root.roles().rolePolicy(server, role);
             Helper.addScopePermission(authz, server, viewPermissionName, resource, viewScope, viewClientsPolicy);
         }
+        String mapRolePermissionName = getMapRolesPermissionName(client);
+        Policy mapRolePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRolePermissionName, server.getId());
+        if (mapRolePermission == null) {
+            Helper.addEmptyScopePermission(authz, server, mapRolePermissionName, resource, mapRoleScope);
+        }
+        String mapRoleClientScopePermissionName = getMapRoleClientScopePermissionName(client);
+        Policy mapRoleClientScopePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleClientScopePermissionName, server.getId());
+        if (mapRoleClientScopePermission == null) {
+            Helper.addEmptyScopePermission(authz, server, mapRoleClientScopePermissionName, resource, mapRoleClientScope);
+        }
+        String mapRoleCompositePermissionName = getMapRoleCompositePermissionName(client);
+        Policy mapRoleCompositePermission = authz.getStoreFactory().getPolicyStore().findByName(mapRoleCompositePermissionName, server.getId());
+        if (mapRoleCompositePermission == null) {
+            Helper.addEmptyScopePermission(authz, server, mapRoleCompositePermissionName, resource, mapRoleCompositeScope);
+        }
+    }
+
+    private void deletePolicy(String name, ClientModel client, ResourceServer server) {
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
+        if (policy != null) {
+            authz.getStoreFactory().getPolicyStore().delete(policy.getId());
+        }
+
     }
 
     private void deletePermissions(ClientModel client) {
-        ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+        ResourceServer server = resourceServer(client);
         if (server == null) return;
-        Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(getManagePermissionName(client), server.getId());
-        if (managePermission != null) {
-            authz.getStoreFactory().getPolicyStore().delete(managePermission.getId());
-        }
-        Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(getViewPermissionName(client), server.getId());
-        if (viewPermission != null) {
-            authz.getStoreFactory().getPolicyStore().delete(viewPermission.getId());
-        }
+        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);
         Resource resource = authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());;
         if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
     }
 
     @Override
     public boolean isPermissionsEnabled(ClientModel client) {
-        ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+        ResourceServer server = resourceServer(client);
         if (server == null) return false;
 
         return authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId()) != null;
@@ -142,6 +187,15 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
     private Scope viewScope(ResourceServer server) {
         return authz.getStoreFactory().getScopeStore().findByName(AdminPermissionManagement.VIEW_SCOPE, server.getId());
     }
+    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() {
@@ -202,7 +256,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             return canManage();
         }
 
-        ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+        ResourceServer server = resourceServer(client);
         if (server == null) return canManage();
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
@@ -236,7 +290,7 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             return canView();
         }
 
-        ResourceServer server = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+        ResourceServer server = resourceServer(client);
         if (server == null) return canView();
 
         Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
@@ -312,4 +366,85 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionMa
             throw new ForbiddenException();
         }
     }
+
+    @Override
+    public boolean canMapRoles(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return false;
+
+        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(getResourceName(client), server.getId());
+        if (resource == null) return false;
+
+        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(getMapRolesPermissionName(client), 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 = mapRolesScope(server);
+        return root.evaluatePermission(resource, scope, server);
+    }
+
+    @Override
+    public Policy mapRolesPermission(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return null;
+        return authz.getStoreFactory().getPolicyStore().findByName(getMapRolesPermissionName(client), server.getId());
+    }
+
+    @Override
+    public ResourceServer resourceServer(ClientModel client) {
+        return authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
+    }
+
+    @Override
+    public boolean canMapCompositeRoles(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return false;
+
+        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());
+        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 = mapRoleCompositeScope(server);
+        return root.evaluatePermission(resource, scope, server);
+    }
+    @Override
+    public boolean canMapClientScopeRoles(ClientModel client) {
+        ResourceServer server = resourceServer(client);
+        if (server == null) return false;
+
+        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());
+        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 = mapRoleClientScope(server);
+        return root.evaluatePermission(resource, scope, server);
+    }
+
 }
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 4167a12..5f666c6 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
@@ -143,6 +143,9 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         if (!root.isAdminSameRealm()) {
             return root.users().canManage();
         }
+        if (role.getContainer() instanceof ClientModel) {
+            if (root.clients().canMapRoles((ClientModel)role.getContainer())) return true;
+        }
         if (!isPermissionsEnabled(role)){
             return root.users().canManage();
         }
@@ -216,6 +219,9 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         if (!root.isAdminSameRealm()) {
             return canManage(role);
         }
+        if (role.getContainer() instanceof ClientModel) {
+            if (root.clients().canMapCompositeRoles((ClientModel)role.getContainer())) return true;
+        }
         if (!isPermissionsEnabled(role)){
             return canManage(role);
         }
@@ -245,6 +251,9 @@ class RolePermissions implements RolePermissionEvaluator, RolePermissionManageme
         if (!root.isAdminSameRealm()) {
             return root.clients().canManage();
         }
+        if (role.getContainer() instanceof ClientModel) {
+            if (root.clients().canMapClientScopeRoles((ClientModel)role.getContainer())) return true;
+        }
         if (!isPermissionsEnabled(role)){
             return root.clients().canManage();
         }
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 488825b..e276ae2 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
@@ -34,6 +34,10 @@ public interface UserPermissionEvaluator {
 
     void requireQuery();
 
+    boolean canQuery(UserModel user);
+
+    void requireQuery(UserModel user);
+
     boolean canView();
     boolean canView(UserModel user);
     void requireView(UserModel user);
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 5e7931b..b095592 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
@@ -291,6 +291,19 @@ class UserPermissions implements UserPermissionEvaluator, UserPermissionManageme
         }
     }
 
+    @Override
+    public boolean canQuery(UserModel user) {
+        return canView(user);
+    }
+
+    @Override
+    public void requireQuery(UserModel user) {
+        if (!canQuery(user)) {
+            throw new ForbiddenException();
+        }
+
+    }
+
 
 
     /**
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index b1cd2e6..fc4bfee 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -192,11 +192,11 @@ public class UsersResource {
      */
     @Path("{id}")
     public UserResource user(final @PathParam("id") String id) {
-        auth.users().requireQuery();
-
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
-            throw new NotFoundException("User not found");
+            // we do this to make sure somebody can't phish ids
+            if (auth.users().canQuery()) throw new NotFoundException("User not found");
+            else throw new ForbiddenException();
         }
         UserResource resource = new UserResource(realm, user, auth, adminEvent);
         ResteasyProviderFactory.getInstance().injectProperties(resource);
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 2b34700..5d413d0 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
@@ -114,6 +114,9 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
         {
             permissions.groups().setPermissionsEnabled(group, true);
         }
+        {
+            permissions.clients().setPermissionsEnabled(client1, true);
+        }
 
     }
 
@@ -156,12 +159,6 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
 
         UserModel user1 = session.users().addUser(realm, "user1");
         user1.setEnabled(true);
-        UserModel user2 = session.users().addUser(realm, "user2");
-        user2.setEnabled(true);
-        UserModel user3 = session.users().addUser(realm, "user3");
-        user3.setEnabled(true);
-        UserModel user4 = session.users().addUser(realm, "user4");
-        user4.setEnabled(true);
 
         // group management
         AdminPermissionManagement permissions = AdminPermissions.management(session, realm);
@@ -188,6 +185,17 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
         Policy groupManagerPermission = permissions.groups().manageMembersPermission(group);
         groupManagerPermission.addAssociatedPolicy(groupManagerPolicy);
 
+        UserModel clientMapper = session.users().addUser(realm, "clientMapper");
+        clientMapper.setEnabled(true);
+        clientMapper.grantRole(managerRole);
+        session.userCredentialManager().updateCredential(realm, clientMapper, UserCredentialModel.password("password"));
+        Policy clientMapperPolicy = permissions.clients().mapRolesPermission(client);
+        UserPolicyRepresentation userRep = new UserPolicyRepresentation();
+        userRep.setName("userClientMapper");
+        userRep.addUser("clientMapper");
+        Policy userPolicy = permissions.authz().getStoreFactory().getPolicyStore().create(userRep, permissions.clients().resourceServer(client));
+        clientMapperPolicy.addAssociatedPolicy(userPolicy);
+
 
 
 
@@ -254,6 +262,17 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
             Assert.assertFalse(permissionsForAdmin.roles().canMapRole(realmRole2));
 
         }
+        // test client.mapRoles
+        {
+            UserModel admin = session.users().getUserByUsername("clientMapper", realm);
+            AdminPermissionEvaluator permissionsForAdmin = AdminPermissions.evaluator(session, realm, realm, admin);
+            UserModel user = session.users().getUserByUsername("authorized", realm);
+            Assert.assertTrue(permissionsForAdmin.users().canManage(user));
+            Assert.assertFalse(permissionsForAdmin.roles().canMapRole(realmRole));
+            Assert.assertTrue(permissionsForAdmin.roles().canMapRole(clientRole));
+            Assert.assertFalse(permissionsForAdmin.roles().canMapRole(realmRole2));
+
+        }
 
     }
 
@@ -283,9 +302,7 @@ 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);
+        UserRepresentation groupMember = adminClient.realm(TEST).users().search("groupMember").get(0);
         RoleRepresentation realmRole = adminClient.realm(TEST).roles().get("realm-role").toRepresentation();
         List<RoleRepresentation> realmRoleSet = new LinkedList<>();
         realmRoleSet.add(realmRole);
@@ -373,6 +390,61 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
             }
         }
 
+        {
+            Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
+                    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();
+            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);
+
+            roles = realmClient.realm(TEST).users().get(user1.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);
+            try {
+                realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRole2Set);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+            try {
+                realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRoleSet);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+
+        }
+
+
+        // test client.mapRoles
+        {
+            Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(),
+                    TEST, "clientMapper", "password", Constants.ADMIN_CLI_CLIENT_ID, null);
+            List<RoleRepresentation> roles = null;
+            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) -> {
+                return r.getName().equals("client-role");
+            }));
+            roles = realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().listAvailable();
+            Assert.assertTrue(roles.isEmpty());
+            try {
+                realmClient.realm(TEST).users().get(user1.getId()).roles().realmLevel().add(realmRoleSet);
+                Assert.fail("should fail with forbidden exception");
+            } catch (ClientErrorException e) {
+                Assert.assertEquals(e.getResponse().getStatus(), 403);
+
+            }
+        }
+
+
     }
 
     @Test