keycloak-aplcache

Merge pull request #2672 from stianst/KEYCLOAK-2491-1.9 KEYCLOAK-2491

4/20/2016 7:49:31 AM

Changes

Details

diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
index 432aae1..0ade972 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
@@ -80,7 +80,8 @@ public class AttackDetectionResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public Map<String, Object> bruteForceUserStatus(@PathParam("username") String username) {
-        auth.hasView();
+        auth.requireView();
+
         Map<String, Object> data = new HashMap<>();
         data.put("disabled", false);
         data.put("numFailures", 0);
@@ -110,6 +111,7 @@ public class AttackDetectionResource {
     @DELETE
     public void clearBruteForceForUser(@PathParam("username") String username) {
         auth.requireManage();
+
         UsernameLoginFailureModel model = session.sessions().getUserLoginFailure(realm, username.toLowerCase());
         if (model != null) {
             session.sessions().removeUserLoginFailure(realm, username);
@@ -127,6 +129,7 @@ public class AttackDetectionResource {
     @DELETE
     public void clearAllBruteForce() {
         auth.requireManage();
+
         session.sessions().removeAllUserLoginFailures(realm);
         adminEvent.operation(OperationType.DELETE).success();
     }
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 1e42aad..a0034e9 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
@@ -101,7 +101,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, Object>> getFormProviders() {
-        this.auth.requireView();
+        auth.requireView();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(FormAuthenticator.class);
         return buildProviderMetadata(factories);
     }
@@ -116,7 +117,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, Object>> getAuthenticatorProviders() {
-        this.auth.requireView();
+        auth.requireView();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(Authenticator.class);
         return buildProviderMetadata(factories);
     }
@@ -131,7 +133,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, Object>> getClientAuthenticatorProviders() {
-        this.auth.requireView();
+        auth.requireAny();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
         return buildProviderMetadata(factories);
     }
@@ -160,7 +163,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, Object>> getFormActionProviders() {
-        this.auth.requireView();
+        auth.requireView();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(FormAction.class);
         return buildProviderMetadata(factories);
     }
@@ -176,7 +180,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<AuthenticationFlowRepresentation> getFlows() {
-        this.auth.requireView();
+        auth.requireAny();
+
         List<AuthenticationFlowRepresentation> flows = new LinkedList<>();
         for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
             if (flow.isTopLevel()) {
@@ -197,7 +202,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public Response createFlow(AuthenticationFlowRepresentation flow) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         if (flow.getAlias() == null || flow.getAlias().isEmpty()) {
             return ErrorResponse.exists("Failed to create flow with empty alias name");
@@ -222,7 +227,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public AuthenticationFlowRepresentation getFlow(@PathParam("id") String id) {
-        this.auth.requireView();
+        auth.requireView();
 
         AuthenticationFlowModel flow = realm.getAuthenticationFlowById(id);
         if (flow == null) {
@@ -240,7 +245,7 @@ public class AuthenticationManagementResource {
     @DELETE
     @NoCache
     public void deleteFlow(@PathParam("id") String id) {
-        this.auth.requireView();
+        auth.requireManage();
 
         AuthenticationFlowModel flow = realm.getAuthenticationFlowById(id);
         if (flow == null) {
@@ -273,7 +278,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         String newName = data.get("newName");
         if (realm.getFlowByAlias(newName) != null) {
@@ -329,7 +334,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
         if (parentFlow == null) {
@@ -377,7 +382,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
         if (parentFlow == null) {
@@ -419,7 +424,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public Response getExecutions(@PathParam("flowAlias") String flowAlias) {
-        this.auth.requireView();
+        auth.requireView();
 
         AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
         if (flow == null) {
@@ -495,7 +500,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public void updateExecutions(@PathParam("flowAlias") String flowAlias, AuthenticationExecutionInfoRepresentation rep) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
         if (flow == null) {
@@ -525,7 +530,8 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public Response addExecution(AuthenticationExecutionRepresentation execution) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         AuthenticationExecutionModel model = RepresentationToModel.toModel(realm, execution);
         AuthenticationFlowModel parentFlow = getParentFlow(model);
         if (parentFlow.isBuiltIn()) {
@@ -557,7 +563,7 @@ public class AuthenticationManagementResource {
     @POST
     @NoCache
     public void raisePriority(@PathParam("executionId") String execution) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
         if (model == null) {
@@ -601,7 +607,7 @@ public class AuthenticationManagementResource {
     @POST
     @NoCache
     public void lowerPriority(@PathParam("executionId") String execution) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
         if (model == null) {
@@ -639,7 +645,7 @@ public class AuthenticationManagementResource {
     @DELETE
     @NoCache
     public void removeExecution(@PathParam("executionId") String execution) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
         if (model == null) {
@@ -673,7 +679,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
     public Response newExecutionConfig(@PathParam("executionId") String execution, AuthenticatorConfigRepresentation json) {
-        this.auth.requireManage();
+        auth.requireManage();
 
         AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
         if (model == null) {
@@ -699,7 +705,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigRepresentation getAuthenticatorConfig(@PathParam("executionId") String execution,@PathParam("id") String id) {
-        this.auth.requireView();
+        auth.requireView();
+
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -718,6 +725,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<Map<String, String>> getUnregisteredRequiredActions() {
+        auth.requireManage();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class);
         List<Map<String, String>> unregisteredList = new LinkedList<>();
         for (ProviderFactory factory : factories) {
@@ -750,6 +759,8 @@ public class AuthenticationManagementResource {
     @Consumes(MediaType.APPLICATION_JSON)
     @NoCache
     public void registereRequiredAction(Map<String, String> data) {
+        auth.requireManage();
+
         String providerId = data.get("providerId");
         String name = data.get("name");
         RequiredActionProviderModel requiredAction = new RequiredActionProviderModel();
@@ -772,6 +783,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RequiredActionProviderRepresentation> getRequiredActions() {
+        auth.requireAny();
+
         List<RequiredActionProviderRepresentation> list = new LinkedList<>();
         for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
             RequiredActionProviderRepresentation rep = toRepresentation(model);
@@ -799,6 +812,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public RequiredActionProviderRepresentation getRequiredAction(@PathParam("alias") String alias) {
+        auth.requireView();
+
         RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
         if (model == null) {
             throw new NotFoundException("Failed to find required action");
@@ -817,7 +832,8 @@ public class AuthenticationManagementResource {
     @PUT
     @Consumes(MediaType.APPLICATION_JSON)
     public void updateRequiredAction(@PathParam("alias") String alias, RequiredActionProviderRepresentation rep) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
         if (model == null) {
             throw new NotFoundException("Failed to find required action");
@@ -840,7 +856,8 @@ public class AuthenticationManagementResource {
     @Path("required-actions/{alias}")
     @DELETE
     public void updateRequiredAction(@PathParam("alias") String alias) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
         if (model == null) {
             throw new NotFoundException("Failed to find required action.");
@@ -856,7 +873,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigInfoRepresentation getAuthenticatorConfigDescription(@PathParam("providerId") String providerId) {
-        this.auth.requireView();
+        auth.requireView();
+
         ConfigurableAuthenticatorFactory factory = CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
         if (factory == null) {
             throw new NotFoundException("Could not find authenticator provider");
@@ -892,7 +910,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
-        this.auth.requireView();
+        auth.requireAny();
+
         List<ProviderFactory> factories = session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);
 
         Map<String, List<ConfigPropertyRepresentation>> toReturn = new HashMap<>();
@@ -921,7 +940,8 @@ public class AuthenticationManagementResource {
     @POST
     @NoCache
     public Response createAuthenticatorConfig(AuthenticatorConfigRepresentation rep) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         AuthenticatorConfigModel config = realm.addAuthenticatorConfig(RepresentationToModel.toModel(rep));
         return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
     }
@@ -935,7 +955,8 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigRepresentation getAuthenticatorConfig(@PathParam("id") String id) {
-        this.auth.requireView();
+        auth.requireView();
+
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -952,7 +973,8 @@ public class AuthenticationManagementResource {
     @DELETE
     @NoCache
     public void removeAuthenticatorConfig(@PathParam("id") String id) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -981,7 +1003,8 @@ public class AuthenticationManagementResource {
     @Consumes(MediaType.APPLICATION_JSON)
     @NoCache
     public void updateAuthenticatorConfig(@PathParam("id") String id, AuthenticatorConfigRepresentation rep) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         AuthenticatorConfigModel exists = realm.getAuthenticatorConfigById(id);
         if (exists == null) {
             throw new NotFoundException("Could not find authenticator config");
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index bea79a0..09186f1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -91,6 +91,8 @@ public class ClientAttributeCertificateResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public CertificateRepresentation getKeyInfo() {
+        auth.requireView();
+
         CertificateRepresentation info = new CertificateRepresentation();
         info.setCertificate(client.getAttribute(certificateAttribute));
         info.setPrivateKey(client.getAttribute(privateAttribute));
@@ -132,6 +134,8 @@ public class ClientAttributeCertificateResource {
     @Consumes(MediaType.MULTIPART_FORM_DATA)
     @Produces(MediaType.APPLICATION_JSON)
     public CertificateRepresentation uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
+        auth.requireManage();
+
         CertificateRepresentation info = getCertFromRequest(uriInfo, input);
 
         if (info.getPrivateKey() != null) {
@@ -163,6 +167,8 @@ public class ClientAttributeCertificateResource {
     @Consumes(MediaType.MULTIPART_FORM_DATA)
     @Produces(MediaType.APPLICATION_JSON)
     public CertificateRepresentation uploadJksCertificate(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
+        auth.requireManage();
+
         CertificateRepresentation info = getCertFromRequest(uriInfo, input);
 
         if (info.getCertificate() != null) {
@@ -239,6 +245,7 @@ public class ClientAttributeCertificateResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public byte[] getKeystore(final KeyStoreConfig config) {
         auth.requireView();
+
         if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
             throw new NotAcceptableException("Only support jks or pkcs12 format.");
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
index 3be39f8..ff766d6 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
@@ -91,6 +91,8 @@ public class ClientInitialAccessResource {
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     public List<ClientInitialAccessPresentation> list() {
+        auth.requireView();
+
         List<ClientInitialAccessModel> models = session.sessions().listClientInitialAccess(realm);
         List<ClientInitialAccessPresentation> reps = new LinkedList<>();
         for (ClientInitialAccessModel m : models) {
@@ -103,6 +105,8 @@ public class ClientInitialAccessResource {
     @DELETE
     @Path("{id}")
     public void delete(final @PathParam("id") String id) {
+        auth.requireManage();
+
         session.sessions().removeClientInitialAccessModel(realm, id);
     }
 
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 09c3dee..2d83e84 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
@@ -147,6 +147,7 @@ public class ClientResource {
     @Produces(MediaType.APPLICATION_JSON)
     public ClientRepresentation getClient() {
         auth.requireView();
+
         return ModelToRepresentation.toRepresentation(client);
     }
 
@@ -165,6 +166,8 @@ public class ClientResource {
     @NoCache
     @Path("installation/providers/{providerId}")
     public Response getInstallationProvider(@PathParam("providerId") String providerId) {
+        auth.requireView();
+
         ClientInstallationProvider provider = session.getProvider(ClientInstallationProvider.class, providerId);
         if (provider == null) throw new NotFoundException("Unknown Provider");
         return provider.generateInstallation(session, realm, client, keycloak.getBaseUri(uriInfo));
@@ -178,6 +181,7 @@ public class ClientResource {
     @NoCache
     public void deleteClient() {
         auth.requireManage();
+
         new ClientManager(new RealmManager(session)).removeClient(realm, client);
         adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
     }
@@ -290,6 +294,7 @@ public class ClientResource {
     @POST
     public GlobalRequestResult pushRevocation() {
         auth.requireManage();
+
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         return new ResourceAdminManager(session).pushClientRevocationPolicy(uriInfo.getRequestUri(), realm, client);
 
@@ -312,6 +317,7 @@ public class ClientResource {
     @Produces(MediaType.APPLICATION_JSON)
     public Map<String, Long> getApplicationSessionCount() {
         auth.requireView();
+
         Map<String, Long> map = new HashMap<>();
         map.put("count", session.sessions().getActiveUserSessions(client.getRealm(), client));
         return map;
@@ -332,6 +338,7 @@ public class ClientResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<UserSessionRepresentation> getUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
         auth.requireView();
+
         firstResult = firstResult != null ? firstResult : -1;
         maxResults = maxResults != null ? maxResults : -1;
         List<UserSessionRepresentation> sessions = new ArrayList<UserSessionRepresentation>();
@@ -359,6 +366,7 @@ public class ClientResource {
     @Produces(MediaType.APPLICATION_JSON)
     public Map<String, Long> getOfflineSessionCount() {
         auth.requireView();
+
         Map<String, Long> map = new HashMap<>();
         map.put("count", session.sessions().getOfflineSessionsCount(client.getRealm(), client));
         return map;
@@ -379,6 +387,7 @@ public class ClientResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<UserSessionRepresentation> getOfflineUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
         auth.requireView();
+
         firstResult = firstResult != null ? firstResult : -1;
         maxResults = maxResults != null ? maxResults : -1;
         List<UserSessionRepresentation> sessions = new ArrayList<UserSessionRepresentation>();
@@ -412,6 +421,7 @@ public class ClientResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void registerNode(Map<String, String> formParams) {
         auth.requireManage();
+
         String node = formParams.get("node");
         if (node == null) {
             throw new BadRequestException("Node not found in params");
@@ -431,6 +441,7 @@ public class ClientResource {
     @NoCache
     public void unregisterNode(final @PathParam("node") String node) {
         auth.requireManage();
+
         if (logger.isDebugEnabled()) logger.debug("Unregister node: " + node);
 
         Integer time = client.getRegisteredNodes().get(node);
@@ -453,6 +464,7 @@ public class ClientResource {
     @NoCache
     public GlobalRequestResult testNodesAvailable() {
         auth.requireManage();
+
         logger.debug("Test availability of cluster nodes");
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         return new ResourceAdminManager(session).testNodesAvailability(uriInfo.getRequestUri(), realm, client);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
index 9acca03..768bf1a 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
@@ -123,6 +123,7 @@ public class ClientTemplateResource {
     @Produces(MediaType.APPLICATION_JSON)
     public ClientTemplateRepresentation getClient() {
         auth.requireView();
+
         return ModelToRepresentation.toRepresentation(template);
     }
 
@@ -134,6 +135,7 @@ public class ClientTemplateResource {
     @NoCache
     public void deleteClientTemplate() {
         auth.requireManage();
+
         realm.removeClientTemplate(template.getId());
         adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
     }
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 429ba5e..36e0179 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
@@ -75,7 +75,7 @@ public class ClientTemplatesResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<ClientTemplateRepresentation> getClientTemplates() {
-        auth.requireAny();
+        auth.requireView();
 
         List<ClientTemplateRepresentation> rep = new ArrayList<>();
         List<ClientTemplateModel> clientModels = realm.getClientTemplates();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
index fb0b104..39e3d4a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
@@ -69,7 +69,8 @@ public class GroupsResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<GroupRepresentation> getGroups() {
-        this.auth.requireView();
+        auth.requireView();
+
         return ModelToRepresentation.toGroupHierarchy(realm, false);
     }
 
@@ -81,7 +82,8 @@ public class GroupsResource {
      */
     @Path("{id}")
     public GroupResource getGroupById(@PathParam("id") String id) {
-        this.auth.requireView();
+        auth.requireView();
+
         GroupModel group = realm.getGroupById(id);
         if (group == null) {
             throw new NotFoundException("Could not find group by id");
@@ -101,7 +103,8 @@ public class GroupsResource {
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     public Response addTopLevelGroup(GroupRepresentation rep) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         GroupModel child = null;
         Response.ResponseBuilder builder = Response.status(204);
         if (rep.getId() != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index b673d83..9e2470b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -28,6 +28,7 @@ import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ServicesLogger;
+import org.keycloak.services.resources.admin.RealmAuth.Resource;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -71,7 +72,7 @@ public class ProtocolMappersResource {
         this.client = client;
         this.adminEvent = adminEvent;
 
-        auth.init(RealmAuth.Resource.USER);
+        auth.init(Resource.CLIENT);
     }
 
     /**
@@ -85,7 +86,8 @@ public class ProtocolMappersResource {
     @Path("protocol/{protocol}")
     @Produces(MediaType.APPLICATION_JSON)
     public List<ProtocolMapperRepresentation> getMappersPerProtocol(@PathParam("protocol") String protocol) {
-        auth.requireView();
+        auth.requireAny();
+
         List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
         for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
             if (mapper.getProtocol().equals(protocol)) mappers.add(ModelToRepresentation.toRepresentation(mapper));
@@ -127,6 +129,7 @@ public class ProtocolMappersResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void createMapper(List<ProtocolMapperRepresentation> reps) {
         auth.requireManage();
+
         ProtocolMapperModel model = null;
         for (ProtocolMapperRepresentation rep : reps) {
             model = RepresentationToModel.toModel(rep);
@@ -145,7 +148,8 @@ public class ProtocolMappersResource {
     @Path("models")
     @Produces(MediaType.APPLICATION_JSON)
     public List<ProtocolMapperRepresentation> getMappers() {
-        auth.requireView();
+        auth.requireAny();
+
         List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
         for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
             mappers.add(ModelToRepresentation.toRepresentation(mapper));
@@ -164,7 +168,8 @@ public class ProtocolMappersResource {
     @Path("models/{id}")
     @Produces(MediaType.APPLICATION_JSON)
     public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) {
-        auth.requireView();
+        auth.requireAny();
+
         ProtocolMapperModel model = client.getProtocolMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         return ModelToRepresentation.toRepresentation(model);
@@ -182,6 +187,7 @@ public class ProtocolMappersResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) {
         auth.requireManage();
+
         ProtocolMapperModel model = client.getProtocolMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         model = RepresentationToModel.toModel(rep);
@@ -199,6 +205,7 @@ public class ProtocolMappersResource {
     @Path("models/{id}")
     public void delete(@PathParam("id") String id) {
         auth.requireManage();
+
         ProtocolMapperModel model = client.getProtocolMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         client.removeProtocolMapper(model);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 058b6e4..67bd7a3 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -54,6 +54,7 @@ import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.GroupRepresentation;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.representations.idm.PartialImportRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -64,6 +65,7 @@ import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.UsersSyncManager;
 import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.resources.admin.RealmAuth.Resource;
 import org.keycloak.timer.TimerProvider;
 
 import javax.ws.rs.Consumes;
@@ -127,6 +129,7 @@ public class RealmAdminResource {
         this.adminEvent = adminEvent.realm(realm);
 
         auth.init(RealmAuth.Resource.REALM);
+        auth.requireAny();
     }
 
     /**
@@ -139,6 +142,8 @@ public class RealmAdminResource {
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     public ClientRepresentation convertClientDescription(String description) {
+        auth.requireManage();
+
         for (ProviderFactory<ClientDescriptionConverter> factory : session.getKeycloakSessionFactory().getProviderFactories(ClientDescriptionConverter.class)) {
             if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
                 return factory.create(session).convertToInternal(description);
@@ -224,6 +229,13 @@ public class RealmAdminResource {
 
             RealmRepresentation rep = new RealmRepresentation();
             rep.setRealm(realm.getName());
+
+            if (auth.init(Resource.IDENTITY_PROVIDER).hasView()) {
+                RealmRepresentation r = ModelToRepresentation.toRepresentation(realm, false);
+                rep.setIdentityProviders(r.getIdentityProviders());
+                rep.setIdentityProviderMappers(r.getIdentityProviderMappers());
+            }
+
             return rep;
         }
     }
@@ -337,6 +349,7 @@ public class RealmAdminResource {
     @POST
     public GlobalRequestResult pushRevocation() {
         auth.requireManage();
+
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         return new ResourceAdminManager(session).pushRealmRevocationPolicy(uriInfo.getRequestUri(), realm);
     }
@@ -350,6 +363,7 @@ public class RealmAdminResource {
     @POST
     public GlobalRequestResult logoutAll() {
         auth.init(RealmAuth.Resource.USER).requireManage();
+
         session.sessions().removeUserSessions(realm);
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         return new ResourceAdminManager(session).logoutAll(uriInfo.getRequestUri(), realm);
@@ -365,6 +379,7 @@ public class RealmAdminResource {
     @DELETE
     public void deleteSession(@PathParam("session") String sessionId) {
         auth.init(RealmAuth.Resource.USER).requireManage();
+
         UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId);
         if (userSession == null) throw new NotFoundException("Sesssion not found");
         AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
@@ -386,6 +401,7 @@ public class RealmAdminResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, String>> getClientSessionStats() {
         auth.requireView();
+
         List<Map<String, String>> data = new LinkedList<Map<String, String>>();
         for (ClientModel client : realm.getClients()) {
             long size = session.sessions().getActiveUserSessions(client.getRealm(), client);
@@ -691,7 +707,8 @@ public class RealmAdminResource {
     @Produces(MediaType.APPLICATION_JSON)
     @Path("default-groups")
     public List<GroupRepresentation> getDefaultGroups() {
-        this.auth.requireView();
+        auth.requireView();
+
         List<GroupRepresentation> defaults = new LinkedList<>();
         for (GroupModel group : realm.getDefaultGroups()) {
             defaults.add(ModelToRepresentation.toRepresentation(group, false));
@@ -702,7 +719,8 @@ public class RealmAdminResource {
     @NoCache
     @Path("default-groups/{groupId}")
     public void addDefaultGroup(@PathParam("groupId") String groupId) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         GroupModel group = realm.getGroupById(groupId);
         if (group == null) {
             throw new NotFoundException("Group not found");
@@ -714,7 +732,8 @@ public class RealmAdminResource {
     @NoCache
     @Path("default-groups/{groupId}")
     public void removeDefaultGroup(@PathParam("groupId") String groupId) {
-        this.auth.requireManage();
+        auth.requireManage();
+
         GroupModel group = realm.getGroupById(groupId);
         if (group == null) {
             throw new NotFoundException("Group not found");
@@ -736,7 +755,8 @@ public class RealmAdminResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public GroupRepresentation getGroupByPath(@PathParam("path") String path) {
-        this.auth.requireView();
+        auth.requireView();
+
         GroupModel found = KeycloakModelUtils.findGroupByPath(realm, path);
         if (found == null) {
             throw new NotFoundException("Group path does not exist");
@@ -756,6 +776,7 @@ public class RealmAdminResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public Response partialImport(PartialImportRepresentation rep) {
         auth.requireManage();
+
         PartialImportManager partialImport = new PartialImportManager(rep, session, realm, adminEvent);
         return partialImport.saveResources();
     }
@@ -768,6 +789,7 @@ public class RealmAdminResource {
     @POST
     public void clearRealmCache() {
         auth.requireManage();
+
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         CacheRealmProvider cache = session.getProvider(CacheRealmProvider.class);
         if (cache != null) {
@@ -783,6 +805,7 @@ public class RealmAdminResource {
     @POST
     public void clearUserCache() {
         auth.requireManage();
+
         adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
         CacheUserProvider cache = session.getProvider(CacheUserProvider.class);
         if (cache != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
index 07efd05..26b1a4a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
@@ -79,8 +79,9 @@ public class RoleByIdResource extends RoleResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public RoleRepresentation getRole(final @PathParam("role-id") String id) {
+        auth.requireAny();
+
         RoleModel roleModel = getRoleModel(id);
-        auth.requireView();
         return getRole(roleModel);
     }
 
@@ -111,8 +112,9 @@ public class RoleByIdResource extends RoleResource {
     @DELETE
     @NoCache
     public void deleteRole(final @PathParam("role-id") String id) {
-        RoleModel role = getRoleModel(id);
         auth.requireManage();
+
+        RoleModel role = getRoleModel(id);
         deleteRole(role);
         adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
     }
@@ -127,8 +129,9 @@ public class RoleByIdResource extends RoleResource {
     @PUT
     @Consumes(MediaType.APPLICATION_JSON)
     public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
-        RoleModel role = getRoleModel(id);
         auth.requireManage();
+
+        RoleModel role = getRoleModel(id);
         updateRole(rep, role);
         adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
     }
@@ -143,8 +146,9 @@ public class RoleByIdResource extends RoleResource {
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
-        RoleModel role = getRoleModel(id);
         auth.requireManage();
+
+        RoleModel role = getRoleModel(id);
         addComposites(adminEvent, uriInfo, roles, role);
     }
 
@@ -161,6 +165,7 @@ public class RoleByIdResource extends RoleResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
+        auth.requireAny();
 
         if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'");
         RoleModel role = getRoleModel(id);
@@ -179,8 +184,9 @@ public class RoleByIdResource extends RoleResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
+        auth.requireAny();
+
         RoleModel role = getRoleModel(id);
-        auth.requireView();
         return getRealmRoleComposites(role);
     }
 
@@ -197,8 +203,9 @@ public class RoleByIdResource extends RoleResource {
     @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-id") String id,
                                                                 final @PathParam("client") String client) {
+        auth.requireAny();
+
         RoleModel role = getRoleModel(id);
-        auth.requireView();
         ClientModel clientModel = realm.getClientById(client);
         if (clientModel == null) {
             throw new NotFoundException("Could not find client");
@@ -219,8 +226,9 @@ public class RoleByIdResource extends RoleResource {
     @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getClientByIdRoleComposites(final @PathParam("role-id") String role,
                                                                 final @PathParam("client") String client) {
+        auth.requireAny();
+
         RoleModel roleModel = getRoleModel(role);
-        auth.requireView();
         ClientModel clientModel = realm.getClientById(client);
         if (clientModel == null) {
             throw new NotFoundException("Could not find client");
@@ -239,8 +247,9 @@ public class RoleByIdResource extends RoleResource {
     @DELETE
     @Consumes(MediaType.APPLICATION_JSON)
     public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
-        RoleModel role = getRoleModel(id);
         auth.requireManage();
+
+        RoleModel role = getRoleModel(id);
         deleteComposites(roles, role);
 
         adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).representation(roles).success();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
index 29b4ae6..ecfc307 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
@@ -100,6 +100,7 @@ public class UserFederationProviderResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void updateProviderInstance(UserFederationProviderRepresentation rep) {
         auth.requireManage();
+
         String displayName = rep.getDisplayName();
         if (displayName != null && displayName.trim().equals("")) {
             displayName = null;
@@ -129,6 +130,7 @@ public class UserFederationProviderResource {
     @Produces(MediaType.APPLICATION_JSON)
     public UserFederationProviderRepresentation getProviderInstance() {
         auth.requireView();
+
         return ModelToRepresentation.toRepresentation(this.federationProviderModel);
     }
 
@@ -157,9 +159,10 @@ public class UserFederationProviderResource {
     @Path("sync")
     @NoCache
     public UserFederationSyncResult syncUsers(@QueryParam("action") String action) {
-        logger.debug("Syncing users");
         auth.requireManage();
 
+        logger.debug("Syncing users");
+
         UsersSyncManager syncManager = new UsersSyncManager();
         UserFederationSyncResult syncResult;
         if ("triggerFullSync".equals(action)) {
@@ -183,7 +186,8 @@ public class UserFederationProviderResource {
     @Path("mapper-types")
     @NoCache
     public Map<String, UserFederationMapperTypeRepresentation> getMapperTypes() {
-        this.auth.requireView();
+        auth.requireView();
+
         KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
         Map<String, UserFederationMapperTypeRepresentation> types = new HashMap<>();
         List<ProviderFactory> factories = sessionFactory.getProviderFactories(UserFederationMapper.class);
@@ -226,7 +230,8 @@ public class UserFederationProviderResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<UserFederationMapperRepresentation> getMappers() {
-        this.auth.requireView();
+        auth.requireView();
+
         List<UserFederationMapperRepresentation> mappers = new LinkedList<>();
         for (UserFederationMapperModel model : realm.getUserFederationMappersByFederationProvider(this.federationProviderModel.getId())) {
             mappers.add(ModelToRepresentation.toRepresentation(realm, model));
@@ -265,6 +270,7 @@ public class UserFederationProviderResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public Response addMapper(UserFederationMapperRepresentation mapper) {
         auth.requireManage();
+
         UserFederationMapperModel model = RepresentationToModel.toModel(realm, mapper);
 
         validateModel(model);
@@ -290,6 +296,7 @@ public class UserFederationProviderResource {
     @Produces(MediaType.APPLICATION_JSON)
     public UserFederationMapperRepresentation getMapperById(@PathParam("id") String id) {
         auth.requireView();
+
         UserFederationMapperModel model = realm.getUserFederationMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         return ModelToRepresentation.toRepresentation(realm, model);
@@ -307,6 +314,7 @@ public class UserFederationProviderResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void update(@PathParam("id") String id, UserFederationMapperRepresentation rep) {
         auth.requireManage();
+
         UserFederationMapperModel model = realm.getUserFederationMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         model = RepresentationToModel.toModel(realm, rep);
@@ -328,6 +336,7 @@ public class UserFederationProviderResource {
     @Path("mappers/{id}")
     public void delete(@PathParam("id") String id) {
         auth.requireManage();
+
         UserFederationMapperModel model = realm.getUserFederationMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         realm.removeUserFederationMapper(model);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
index 9c9ac51..d7e66b1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
@@ -134,6 +134,7 @@ public class UserFederationProvidersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<UserFederationProviderFactoryRepresentation> getProviders() {
         auth.requireView();
+
         List<UserFederationProviderFactoryRepresentation> providers = new LinkedList<UserFederationProviderFactoryRepresentation>();
         for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
             UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
@@ -155,6 +156,7 @@ public class UserFederationProvidersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) {
         auth.requireView();
+
         for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
             if (!factory.getId().equals(id)) {
                 continue;
@@ -192,6 +194,7 @@ public class UserFederationProvidersResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public Response createProviderInstance(UserFederationProviderRepresentation rep) {
         auth.requireManage();
+
         String displayName = rep.getDisplayName();
         if (displayName != null && displayName.trim().equals("")) {
             displayName = null;
@@ -225,6 +228,7 @@ public class UserFederationProvidersResource {
     @NoCache
     public List<UserFederationProviderRepresentation> getUserFederationInstances() {
         auth.requireManage();
+
         List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
         for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
             UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
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 5427a1a..169eef7 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
@@ -313,6 +313,7 @@ public class UsersResource {
     public Map<String, Object> impersonate(final @PathParam("id") String id) {
         auth.init(RealmAuth.Resource.IMPERSONATION);
         auth.requireManage();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -357,6 +358,7 @@ public class UsersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id) {
         auth.requireView();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -382,6 +384,7 @@ public class UsersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<UserSessionRepresentation> getSessions(final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
         auth.requireView();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -420,6 +423,7 @@ public class UsersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<FederatedIdentityRepresentation> getFederatedIdentity(final @PathParam("id") String id) {
         auth.requireView();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -456,6 +460,7 @@ public class UsersResource {
     @NoCache
     public Response addFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider, FederatedIdentityRepresentation rep) {
         auth.requireManage();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -481,6 +486,7 @@ public class UsersResource {
     @NoCache
     public void removeFederatedIdentity(final @PathParam("id") String id, final @PathParam("provider") String provider) {
         auth.requireManage();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -503,6 +509,7 @@ public class UsersResource {
     @Produces(MediaType.APPLICATION_JSON)
     public List<Map<String, Object>> getConsents(final @PathParam("id") String id) {
         auth.requireView();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -555,6 +562,7 @@ public class UsersResource {
     @NoCache
     public void revokeConsent(final @PathParam("id") String id, final @PathParam("client") String clientId) {
         auth.requireManage();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
@@ -586,6 +594,7 @@ public class UsersResource {
     @POST
     public void logout(final @PathParam("id") String id) {
         auth.requireManage();
+
         UserModel user = session.users().getUserById(id, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
index aebc6c1..35f3849 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
@@ -72,6 +72,9 @@ public class ImpersonationTest {
                 UserModel masterImpersonator = manager.getSession().users().addUser(adminstrationRealm, "master-impersonator");
                 masterImpersonator.setEnabled(true);
                 ClientModel adminRealmClient = adminstrationRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(appRealm.getName()));
+                RoleModel masterManageUsersRole = adminRealmClient.getRole(AdminRoles.MANAGE_USERS);
+                masterImpersonator.grantRole(masterManageUsersRole);
+
                 RoleModel masterImpersonatorRole = adminRealmClient.getRole(ImpersonationConstants.IMPERSONATION_ROLE);
                 masterImpersonator.grantRole(masterImpersonatorRole);
             }
@@ -84,6 +87,10 @@ public class ImpersonationTest {
                 UserModel impersonator = manager.getSession().users().addUser(appRealm, "impersonator");
                 impersonator.setEnabled(true);
                 ClientModel appRealmClient = appRealm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
+
+                RoleModel masterManageUsersRole = appRealmClient.getRole(AdminRoles.MANAGE_USERS);
+                impersonator.grantRole(masterManageUsersRole);
+
                 RoleModel realmImpersonatorRole = appRealmClient.getRole(ImpersonationConstants.IMPERSONATION_ROLE);
                 impersonator.grantRole(realmImpersonatorRole);
             }
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 8bac7bf..eb215e0 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -40,6 +40,10 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
             return getAccess('view-events') || getAccess('manage-events') || this.manageClients;
         },
 
+        get viewIdentityProviders() {
+            return getAccess('view-identity-providers') || getAccess('manage-identity-providers') || this.manageIdentityProviders;
+        },
+
         get manageRealm() {
             return getAccess('manage-realm');
         },
@@ -55,6 +59,11 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
         get manageEvents() {
             return getAccess('manage-events');
         },
+
+        get manageIdentityProviders() {
+            return getAccess('manage-identity-providers');
+        },
+
         get impersonation() {
             return getAccess('impersonation');
         }
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-initial-access.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-initial-access.html
index 97c1fbb..11b3dcf 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-initial-access.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-initial-access.html
@@ -15,7 +15,7 @@
                         </div>
                     </div>
 
-                    <div class="pull-right" data-ng-show="access.manageRealm">
+                    <div class="pull-right" data-ng-show="access.manageClients">
                         <a id="createClient" class="btn btn-default" href="#/realms/{{realm.realm}}/client-initial-access/create">{{:: 'create' | translate}}</a>
                     </div>
                 </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index 9347274..7f796e9 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -42,7 +42,7 @@
             </td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</td>
             <td class="kc-action-cell" data-ng-click="exportClient(client)">{{:: 'export' | translate}}</td>
-            <td class="kc-action-cell" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
+            <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
         </tr>
         <tr data-ng-show="(clients | filter:search).length == 0">
             <td class="text-muted" colspan="3" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
index c07e732..ba9b9bf 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-mappers.html
@@ -55,7 +55,7 @@
             <td>{{mapperTypes[mapper.protocolMapper].category}}</td>
             <td>{{mapperTypes[mapper.protocolMapper].name}}</td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">{{:: 'edit' | translate}}</td>
-            <td class="kc-action-cell" data-ng-click="removeMapper(mapper)">{{:: 'delete' | translate}}</td>
+            <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeMapper(mapper)">{{:: 'delete' | translate}}</td>
         </tr>
         <tr data-ng-show="mappers.length == 0">
             <td>{{:: 'no-mappers-available' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
index 37dde5c..38560e8 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-revocation.html
@@ -7,7 +7,7 @@
 
     <kc-tabs-client></kc-tabs-client>
 
-    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
+    <form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients">
         <fieldset class="border-top">
             <div class="form-group">
                 <label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
index 52154d7..da4d49d 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-role-list.html
@@ -29,7 +29,7 @@
             <td translate="{{role.composite}}"></td>
             <td>{{role.description}}</td>
             <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{:: 'edit' | translate}}</td>
-            <td class="kc-action-cell" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
+            <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
         </tr>
         <tr data-ng-show="!roles || roles.length == 0">
             <td>{{:: 'no-client-roles-available' | translate}}</td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
index 5852634..cd2964d 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mapper-detail.html
@@ -7,11 +7,11 @@
         <li class="active" data-ng-hide="create">{{mapper.name|capitalize}}</li>
     </ol>
 
-    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageRealm" 
+    <h1 data-ng-hide="create">{{mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageIdentityProviders"
     	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
     <h1 data-ng-show="create">{{:: 'add-identity-provider-mapper' | translate}}</h1>
 
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageIdentityProviders">
         <fieldset>
             <div class="form-group clearfix" data-ng-show="!create">
                 <label class="col-md-2 control-label" for="mapperId">{{:: 'id' | translate}} </label>
@@ -48,14 +48,14 @@
             <kc-provider-config config="mapper.config" properties="mapperType.properties" realm="realm"></kc-provider-config>
         </fieldset>
 
-        <div class="form-group" data-ng-show="create && access.manageRealm">
+        <div class="form-group" data-ng-show="create && access.manageIdentityProviders">
             <div class="col-md-10 col-md-offset-2">
                 <button kc-save>{{:: 'save' | translate}}</button>
                 <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
 
-        <div class="form-group" data-ng-show="!create && access.manageRealm">
+        <div class="form-group" data-ng-show="!create && access.manageIdentityProviders">
             <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">{{:: 'cancel' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html b/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
index 7950d6f..a2f7eff 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/identity-provider-mappers.html
@@ -19,7 +19,7 @@
                             </div>
                         </div>
                     </div>
-                    <div class="pull-right">
+                    <div class="pull-right" data-ng-show="access.manageIdentityProviders">
                         <a class="btn btn-primary" href="#/create/identity-provider-mappers/{{realm.realm}}/{{identityProvider.alias}}">{{:: 'create' | translate}}</a>
                     </div>
                 </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
index 29aa688..fe781c2 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
@@ -1,8 +1,8 @@
     <h1 data-ng-show="model.create">{{:: 'create-protocol-mapper' | translate}}</h1>
-    <h1 data-ng-hide="model.create">{{model.mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!model.create && access.manageRealm"
+    <h1 data-ng-hide="model.create">{{model.mapper.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!model.create && access.manageClients"
     	data-ng-hide="model.changed" data-ng-click="remove()"></i></h1>
 
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
 
         <fieldset>
             <div class="form-group clearfix">
@@ -64,14 +64,14 @@
         </fieldset>
 
         <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="model.create && access.manageRealm">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="model.create && access.manageClients">
                 <button kc-save>{{:: 'save' | translate}}</button>
                 <button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
             </div>
         </div>
 
         <div class="form-group">
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!model.create && access.manageRealm">
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!model.create && access.manageClients">
                 <button kc-save  data-ng-disabled="!model.changed">{{:: 'save' | translate}}</button>
                 <button kc-reset data-ng-disabled="!model.changed">{{:: 'cancel' | translate}}</button>
             </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
index 71a8c5a..1b1ae96 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
@@ -9,7 +9,7 @@
                     <thead>
                     <tr>
                         <th colspan="6" class="kc-table-actions">
-                            <div class="dropdown pull-right">
+                            <div class="dropdown pull-right" data-ng-show="access.manageIdentityProviders">
                                 <select class="form-control" ng-model="provider"
                                         ng-options="p.name group by p.groupName for p in allProviders track by p.id"
                                         data-ng-change="addProvider(provider); provider = null">
@@ -35,7 +35,7 @@
                         <td translate="{{identityProvider.enabled}}"></td>
                         <td>{{identityProvider.config.guiOrder}}</td>
                         <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{:: 'edit' | translate}}</td>
-                        <td class="kc-action-cell" data-ng-click="removeIdentityProvider(identityProvider)">{{:: 'delete' | translate}}</td>
+                        <td class="kc-action-cell" data-ng-show="access.manageIdentityProviders" data-ng-click="removeIdentityProvider(identityProvider)">{{:: 'delete' | translate}}</td>
                     </tr>
                     </tbody>
                 </table>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 86c0102..1db4c6a 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -6,7 +6,7 @@
 
     <kc-tabs-identity-provider></kc-tabs-identity-provider>
 
-    <form class="form-horizontal" name="realmForm" novalidate>
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageIdentityProviders">
         <input type="text" readonly value="this is not a login form" style="display: none;">
         <input type="password" readonly value="this is not a login form" style="display: none;">
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 2abfeb8..aa94559 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -6,7 +6,7 @@
 
     <kc-tabs-identity-provider></kc-tabs-identity-provider>
 
-    <form class="form-horizontal" name="realmForm" novalidate>
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageIdentityProviders">
         <fieldset>
             <div class="form-group clearfix">
                 <label class="col-md-2 control-label" for="redirectUri">{{:: 'redirect-uri' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 29e85af..9599d98 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -6,7 +6,7 @@
 
     <kc-tabs-identity-provider></kc-tabs-identity-provider>
 
-    <form class="form-horizontal" name="realmForm" novalidate>
+    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageIdentityProviders">
         <input type="text" readonly value="this is not a login form" style="display: none;">
         <input type="password" readonly value="this is not a login form" style="display: none;">
 
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 d585672..6939b26 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
@@ -113,7 +113,7 @@
                 </div>
             </div>
 
-            <div class="form-group clearfix" data-ng-hide="create">
+            <div class="form-group clearfix" data-ng-hide="create || !access.impersonation">
                 <label class="col-md-2 control-label" for="impersonate">{{:: 'impersonate-user' | translate}}</label>
 
                 <div class="col-md-6">
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
index 0b34e7f..e766bcb 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-menu.html
@@ -32,8 +32,8 @@
             <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'clients' || path[1] == 'client' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients"><i class="fa fa-cube"></i> {{:: 'clients' | translate}}</a></li>
             <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'client-templates' || path[1] == 'client-template' || path[3] == 'client-templates') && 'active'"><a href="#/realms/{{realm.realm}}/client-templates"><i class="fa fa-cubes"></i> {{:: 'client-templates' | translate}}</a></li>
             <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || path[2] == 'default-roles' || (path[1] == 'role' && path[3] != 'clients')) && 'active'"><a href="#/realms/{{realm.realm}}/roles"><i class="fa fa-tasks"></i> {{:: 'roles' | translate}}</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> {{:: 'identity-providers' | translate}}</a></li>
-            <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'user-federation' || path[2] == 'user-federation') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> {{:: 'user-federation' | translate}}</a></li>
+            <li data-ng-show="access.viewIdentityProviders" data-ng-class="(path[2] == 'identity-provider-settings' || path[2] == 'identity-provider-mappers') && 'active'"><a href="#/realms/{{realm.realm}}/identity-provider-settings"><i class="fa fa-exchange"></i> {{:: 'identity-providers' | translate}}</a></li>
+            <li data-ng-show="access.viewUsers" data-ng-class="(path[1] == 'user-federation' || path[2] == 'user-federation') && 'active'"><a href="#/realms/{{realm.realm}}/user-federation"><i class="fa fa-database"></i> {{:: 'user-federation' | translate}}</a></li>
             <li data-ng-show="access.viewRealm" data-ng-class="(path[1] == 'authentication' || path[2] == 'authentication') && 'active'"><a href="#/realms/{{realm.realm}}/authentication/flows"><i class="fa fa-lock"></i> {{:: 'authentication' | translate}}</a></li>
         </ul>
     </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group-list.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group-list.html
index 6542f21..5b67035 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-group-list.html
@@ -5,7 +5,7 @@
 
     <ul class="nav nav-tabs">
         <li ng-class="{active: path[2] == 'groups'}"><a href="#/realms/{{realm.realm}}/groups">{{:: 'groups' | translate}}</a></li>
-        <li ng-class="{active: path[2] == 'default-groups'}"><a href="#/realms/{{realm.realm}}/default-groups">{{:: 'default-groups' | translate}}</a><kc-tooltip>{{:: 'groups.default-groups.tooltip' | translate}}</kc-tooltip>
+        <li data-ng-show="access.viewRealm" ng-class="{active: path[2] == 'default-groups'}"><a href="#/realms/{{realm.realm}}/default-groups">{{:: 'default-groups' | translate}}</a><kc-tooltip>{{:: 'groups.default-groups.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-realm.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-realm.html
index 5d14503..7f10767 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-realm.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-realm.html
@@ -13,7 +13,7 @@
         <li ng-class="{active: path[2] == 'theme-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/theme-settings">{{:: 'realm-tab-themes' | translate}}</a></li>
         <li ng-class="{active: path[2] == 'cache-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/cache-settings">{{:: 'realm-tab-cache' | translate}}</a></li>
         <li ng-class="{active: path[2] == 'token-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/token-settings">{{:: 'realm-tab-tokens' | translate}}</a></li>
-        <li ng-class="{active: path[2] == 'client-initial-access'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/client-initial-access">{{:: 'realm-tab-client-initial-access' | translate}}</a></li>
+        <li ng-class="{active: path[2] == 'client-initial-access'}" data-ng-show="access.viewClients"><a href="#/realms/{{realm.realm}}/client-initial-access">{{:: 'realm-tab-client-initial-access' | translate}}</a></li>
         <li ng-class="{active: path[2] == 'defense'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/defense/headers">{{:: 'realm-tab-security-defenses' | translate}}</a></li>
     </ul>
 </div>
\ No newline at end of file