keycloak-developers

Changes

forms/common-themes/src/main/resources/theme/base/login/impersonate.ftl 45(+0 -45)

services/src/main/java/org/keycloak/services/resources/ImpersonationService.java 177(+0 -177)

Details

diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index e9341b3..335bef3 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -79,6 +79,9 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
 
         get manageEvents() {
             return getAccess('manage-events');
+        },
+        get impersonation() {
+            return getAccess('impersonation');
         }
     }
 
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
index 55f6788..2bb3b29 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
@@ -210,7 +210,7 @@ module.controller('UserConsentsCtrl', function($scope, realm, user, userConsents
 });
 
 
-module.controller('UserListCtrl', function($scope, realm, User) {
+module.controller('UserListCtrl', function($scope, realm, User, UserImpersonation) {
     $scope.realm = realm;
     $scope.page = 0;
 
@@ -220,6 +220,16 @@ module.controller('UserListCtrl', function($scope, realm, User) {
         first : 0
     }
 
+    $scope.impersonate = function(userId) {
+        UserImpersonation.save({realm : realm.realm, user: userId}, function (data) {
+            if (data.sameRealm) {
+                window.location = data.redirect;
+            } else {
+                window.open(data.redirect, "_blank");
+            }
+        });
+    };
+
     $scope.firstPage = function() {
         $scope.query.first = 0;
         $scope.searchQuery();
@@ -251,7 +261,7 @@ module.controller('UserListCtrl', function($scope, realm, User) {
 
 
 
-module.controller('UserDetailCtrl', function($scope, realm, user, User, UserFederationInstances, RequiredActions, $location, Dialog, Notifications) {
+module.controller('UserDetailCtrl', function($scope, realm, user, User, UserFederationInstances, UserImpersonation, RequiredActions, $location, Dialog, Notifications) {
     $scope.realm = realm;
     $scope.create = !user.id;
     $scope.editUsername = $scope.create || $scope.realm.editUsernameAllowed;
@@ -264,7 +274,17 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, UserFede
         }
         convertAttributeValuesToString(user);
 
+
         $scope.user = angular.copy(user);
+        $scope.impersonate = function() {
+            UserImpersonation.save({realm : realm.realm, user: $scope.user.id}, function (data) {
+                if (data.sameRealm) {
+                    window.location = data.redirect;
+                } else {
+                    window.open(data.redirect, "_blank");
+                }
+            });
+        };
         if(user.federationLink) {
             console.log("federationLink is not null");
             UserFederationInstances.get({realm : realm.realm, instance: user.federationLink}, function(link) {
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index 3f79536..0398bfa 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -328,6 +328,13 @@ module.factory('UserConsents', function($resource) {
     });
 });
 
+module.factory('UserImpersonation', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/users/:user/impersonation', {
+        realm : '@realm',
+        user : '@user'
+    });
+});
+
 module.factory('UserCredentials', function($resource) {
     var credentials = {};
 
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
index 94bf899..898650b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
@@ -8,8 +8,8 @@
 
     <kc-tabs-user></kc-tabs-user>
 
-    <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageUsers">
-        <div class="form-group">
+    <form class="form-horizontal" name="realmForm" novalidate>
+        <div class="form-group" kc-read-only="!access.manageUsers">
             <label class="col-md-2 control-label" class="control-label">Realm Roles</label>
 
             <div class="col-md-10">
@@ -56,7 +56,7 @@
                     <span>Client Roles</span>
                     <select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
                 </label>
-                <div class="col-md-10">
+                <div class="col-md-10" kc-read-only="!access.manageUsers">
                     <div class="row" data-ng-hide="client">
                         <div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
                     </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
index 6779d42..10a2e72 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
@@ -5,8 +5,8 @@
         <li data-ng-show="create">Add User</li>
     </ol>
 
-    <h1 data-ng-hide="create">{{user.username|capitalize}}<i style="padding-left: 20px" class="pficon pficon-delete" data-ng-show="!create && access.manageUsers" 
-    	data-ng-hide="changed" data-ng-click="remove()"></i></h1>
+    <h1 data-ng-hide="create">{{user.username|capitalize}}<i style="padding-left: 20px" class="pficon pficon-delete" data-ng-show="!create && access.manageUsers && !changed"
+    	data-ng-click="remove()"></i></h1>
     <h1 data-ng-show="create">Add User</h1>
 
     <kc-tabs-user></kc-tabs-user>
@@ -66,7 +66,7 @@
             <div class="form-group clearfix block">
                 <label class="col-md-2 control-label" for="userEnabled">User Enabled</label>
                 <div class="col-md-6">
-                    <input ng-model="user.enabled" name="userEnabled" id="userEnabled" onoffswitch />
+                    <input ng-model="user.enabled" name="userEnabled" id="userEnabled" ng-disabled="!access.manageUsers" onoffswitch />
                 </div>
                 <kc-tooltip>A disabled user cannot login.</kc-tooltip>
             </div>
@@ -79,7 +79,7 @@
             <div class="form-group clearfix block">
                 <label class="col-md-2 control-label" for="emailVerified">Email verified</label>
                 <div class="col-md-6">
-                    <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" onoffswitch />
+                    <input ng-model="user.emailVerified" name="emailVerified" id="emailVerified" ng-disabled="!access.manageUsers" onoffswitch />
                 </div>
                 <kc-tooltip>Has the user's email been verified?</kc-tooltip>
             </div>
@@ -116,13 +116,14 @@
                 <button kc-cancel data-ng-click="cancel()">Cancel</button>
             </div>
 
-            <div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageUsers">
-                <button kc-save  data-ng-show="changed">Save</button>
-                <button kc-reset data-ng-show="changed">Cancel</button>
+            <div class="col-md-10 col-md-offset-2" data-ng-show="!create">
+                <button kc-save  data-ng-show="access.manageUsers && changed">Save</button>
+                <button kc-reset data-ng-show="access.manageUsers && changed">Cancel</button>
+                <button data-ng-show="access.impersonation" class="btn btn-default" data-ng-click="impersonate()">Impersonate</button>
             </div>
         </div>
 
     </form>
 </div>
 
-<kc-menu></kc-menu>
+<kc-menu></kc-menu>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
index 9a042e3..dc2c4ac 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-list.html
@@ -5,7 +5,7 @@
         <caption data-ng-show="users" class="hidden">Table of realm users</caption>
         <thead>
         <tr>
-            <th colspan="4">
+            <th colspan="{{access.impersonation == true ? '5' : '4'}}">
                 <div class="form-inline">
                     <div class="form-group">
                         <div class="input-group">
@@ -17,7 +17,7 @@
                     </div>
                     <button class="btn btn-primary" ng-click="query.search = null; firstPage()">View all users</button>
 
-                    <div class="pull-right">
+                    <div class="pull-right" data-ng-show="access.manageUsers">
                         <a class="btn btn-primary" href="#/create/user/{{realm.realm}}">Add User</a>
                     </div>
                 </div>
@@ -29,6 +29,7 @@
             <th>Last Name</th>
             <th>First Name</th>
             <th>Email</th>
+            <th data-ng-show="access.impersonation"></th>
         </tr>
         </tr>
         </thead>
@@ -49,6 +50,7 @@
             <td>{{user.lastName}}</td>
             <td>{{user.firstName}}</td>
             <td>{{user.email}}</td>
+            <td data-ng-show="access.impersonation"><button class="btn btn-default" data-ng-click="impersonate(user.id)">Impersonate</button></td>
         </tr>
         <tr data-ng-show="!users || users.length == 0">
             <td class="text-muted" data-ng-show="!users">Please enter a search, or click on view all users</td>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
index 762dda9..685549d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
@@ -1,4 +1,4 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
+    <div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/users">Users</a></li>
         <li>{{user.username}}</li>
@@ -10,9 +10,9 @@
 
     <table class="table table-striped table-bordered">
         <thead>
-        <tr>
+        <tr data-ng-show="access.manageUsers">
             <th class="kc-table-actions" colspan="6">
-                <div class="pull-right">
+                <div class="pull-right" data-ng-show="access.manageUsers">
                     <a class="btn btn-primary" ng-click="logoutAll()">Logout All Sessions</a>
                 </div>
             </th>
@@ -22,7 +22,7 @@
             <th>Started</th>
             <th>Last Access</th>
             <th>Clients</th>
-            <th>Action</th>
+            <th data-ng-show="access.manageUsers">Action</th>
         </tr>
         </thead>
         <tbody>
@@ -36,7 +36,7 @@
                 </div>
             </ul>
             </td>
-            <td><a href="" ng-click="logoutSession(session.id)">logout</a> </td>
+            <td data-ng-show="access.manageUsers"><a  href="" ng-click="logoutSession(session.id)">logout</a> </td>
         </tr>
         </tbody>
     </table>
diff --git a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
index 734c472..4f49a17 100755
--- a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
+++ b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
@@ -1,7 +1,7 @@
 package org.keycloak.migration.migrators;
 
 import org.keycloak.migration.ModelVersion;
-import org.keycloak.models.ImpersonationServiceConstants;
+import org.keycloak.models.ImpersonationConstants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.DefaultAuthenticationFlows;
@@ -23,7 +23,7 @@ public class MigrateTo1_4_0 {
                 DefaultAuthenticationFlows.addFlows(realm);
                 DefaultRequiredActions.addActions(realm);
             }
-            ImpersonationServiceConstants.setupImpersonationService(session, realm, session.getContext().getContextPath());
+            ImpersonationConstants.setupImpersonationService(session, realm);
 
         }
 
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index b99c1c8..1aff2ed 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -9,7 +9,7 @@ import org.keycloak.models.AdminRoles;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.BrowserSecurityHeaders;
 import org.keycloak.models.Constants;
-import org.keycloak.models.ImpersonationServiceConstants;
+import org.keycloak.models.ImpersonationConstants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
@@ -236,7 +236,7 @@ public class RealmManager {
     }
 
     public void setupImpersonationService(RealmModel realm) {
-        ImpersonationServiceConstants.setupImpersonationService(session, realm, contextPath);
+        ImpersonationConstants.setupImpersonationService(session, realm);
     }
 
     public void setupBrokerService(RealmModel realm) {
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 39ef7c3..e6c186b 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
@@ -56,7 +56,7 @@ public class AuthenticationManagementResource {
         this.realm = realm;
         this.session = session;
         this.auth = auth;
-        this.auth.init(RealmAuth.Resource.IDENTITY_PROVIDER);
+        this.auth.init(RealmAuth.Resource.REALM);
         this.adminEvent = adminEvent;
     }
 
@@ -140,6 +140,7 @@ public class AuthenticationManagementResource {
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     public List<AuthenticationFlowModel> getFlows() {
+        this.auth.requireView();
         List<AuthenticationFlowModel> flows = new LinkedList<>();
         for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
             if (flow.isTopLevel()) {
@@ -265,6 +266,7 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigModel getAuthenticatorConfig(@PathParam("executionId") String execution,@PathParam("id") String id) {
+        this.auth.requireView();
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -363,6 +365,7 @@ public class AuthenticationManagementResource {
     @PUT
     @Consumes(MediaType.APPLICATION_JSON)
     public void updateRequiredAction(@PathParam("alias") String alias, RequiredActionProviderRepresentation rep) {
+        this.auth.requireManage();
         RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
         if (model == null) {
             throw new NotFoundException("Failed to find required action: " + alias);
@@ -381,6 +384,7 @@ public class AuthenticationManagementResource {
     @Path("required-actions/{alias}")
     @DELETE
     public void updateRequiredAction(@PathParam("alias") String alias) {
+        this.auth.requireManage();
         RequiredActionProviderModel model = realm.getRequiredActionProviderByAlias(alias);
         if (model == null) {
             throw new NotFoundException("Failed to find required action: " + alias);
@@ -434,6 +438,7 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigDescription getAuthenticatorConfigDescription(@PathParam("providerId") String providerId) {
+        this.auth.requireView();
         ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(providerId);
         if (factory == null) {
             throw new NotFoundException("Could not find authenticator provider");
@@ -460,6 +465,7 @@ public class AuthenticationManagementResource {
     @POST
     @NoCache
     public Response createAuthenticatorConfig(AuthenticatorConfigModel config) {
+        this.auth.requireManage();
         config = realm.addAuthenticatorConfig(config);
         return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build();
     }
@@ -469,6 +475,7 @@ public class AuthenticationManagementResource {
     @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public AuthenticatorConfigModel getAuthenticatorConfig(@PathParam("id") String id) {
+        this.auth.requireView();
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -480,6 +487,7 @@ public class AuthenticationManagementResource {
     @DELETE
     @NoCache
     public void removeAuthenticatorConfig(@PathParam("id") String id) {
+        this.auth.requireManage();
         AuthenticatorConfigModel config = realm.getAuthenticatorConfigById(id);
         if (config == null) {
             throw new NotFoundException("Could not find authenticator config");
@@ -502,6 +510,7 @@ public class AuthenticationManagementResource {
     @Consumes(MediaType.APPLICATION_JSON)
     @NoCache
     public void updateAuthenticatorConfig(@PathParam("id") String id, AuthenticatorConfigModel config) {
+        this.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/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 5280a97..85779bc 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -280,6 +280,7 @@ public class RealmAdminResource {
     @Path("logout-all")
     @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);
@@ -294,6 +295,7 @@ public class RealmAdminResource {
     @Path("sessions/{session}")
     @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);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
index f93e8c7..fc778d0 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
@@ -2,6 +2,7 @@ package org.keycloak.services.resources.admin;
 
 import org.keycloak.models.AdminRoles;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ImpersonationConstants;
 import org.keycloak.services.ForbiddenException;
 
 
@@ -13,7 +14,7 @@ public class RealmAuth {
     private Resource resource;
 
     public enum Resource {
-        CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER
+        CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER, IMPERSONATION
     }
 
     private AdminAuth auth;
@@ -29,6 +30,10 @@ public class RealmAuth {
         return this;
     }
 
+    public AdminAuth getAuth() {
+        return auth;
+    }
+
     public void requireAny() {
         if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
             throw new ForbiddenException();
@@ -84,6 +89,8 @@ public class RealmAuth {
                 return AdminRoles.MANAGE_EVENTS;
             case IDENTITY_PROVIDER:
                 return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
+            case IMPERSONATION:
+                return ImpersonationConstants.IMPERSONATION_ROLE;
             default:
                 throw new IllegalStateException();
         }
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 0b56278..e84d5ae 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
@@ -61,6 +61,7 @@ import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.WebApplicationException;
 
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -72,6 +73,7 @@ import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import org.keycloak.models.UsernameLoginFailureModel;
 import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.resources.AccountService;
 
 /**
  * Base resource for managing users
@@ -270,6 +272,37 @@ public class UsersResource {
         return rep;
     }
 
+    @Path("{id}/impersonation")
+    @POST
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    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");
+        }
+        RealmModel authenticatedRealm = auth.getAuth().getRealm();
+        // if same realm logout before impersonation
+        boolean sameRealm = false;
+        if (authenticatedRealm.getId().equals(realm.getId())) {
+            sameRealm = true;
+            UserSessionModel userSession = session.sessions().getUserSession(authenticatedRealm, auth.getAuth().getToken().getSessionState());
+            AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
+            AuthenticationManager.expireRememberMeCookie(realm, uriInfo, clientConnection);
+            AuthenticationManager.backchannelLogout(session, authenticatedRealm, userSession, uriInfo, clientConnection, headers, true);
+        }
+        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "impersonate", false, null, null);
+        AuthenticationManager.createLoginCookie(realm, userSession.getUser(), userSession, uriInfo, clientConnection);
+        URI redirect = AccountService.accountServiceApplicationPage(uriInfo).build(realm.getName());
+        Map<String, Object> result = new HashMap<>();
+        result.put("sameRealm", sameRealm);
+        result.put("redirect", redirect.toString());
+        return result;
+    }
+
+
     /**
      * List set of sessions associated with this user.
      *
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index a5fe083..ee91b43 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -148,22 +148,6 @@ public class RealmsResource {
         return accountService;
     }
 
-    @Path("{realm}/impersonate")
-    public ImpersonationService getImpersonationService(final @PathParam("realm") String name) {
-        RealmModel realm = init(name);
-
-        ClientModel client = realm.getClientNameMap().get(Constants.IMPERSONATION_SERVICE_CLIENT_ID);
-        if (client == null || !client.isEnabled()) {
-            logger.debug("impersonate service not enabled");
-            throw new NotFoundException("impersonate service not enabled");
-        }
-
-        EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        ImpersonationService impersonateService = new ImpersonationService(realm, client, event);
-        ResteasyProviderFactory.getInstance().injectProperties(impersonateService);
-        return impersonateService;
-    }
-
     @Path("{realm}")
     public PublicRealmResource getRealmResource(final @PathParam("realm") String name) {
         RealmModel realm = init(name);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
index 01a8ed9..c30ee36 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
@@ -42,7 +42,7 @@ public class ClientTest extends AbstractClientTest {
 
     @Test
     public void getClients() {
-        assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", "impersonation");
+        assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker");
     }
 
     private String createClient() {
@@ -59,7 +59,7 @@ public class ClientTest extends AbstractClientTest {
         String id = createClient();
 
         assertNotNull(realm.clients().get(id));
-        assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", "my-app", "impersonation");
+        assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", "my-app");
     }
 
     @Test
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
index 0141166..86ca62e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
@@ -86,7 +86,7 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertEquals(0,  session.users().getFederatedIdentities(user, realm).size());
 
         List<ClientModel> resources = realm.getClients();
-        Assert.assertEquals(8, resources.size());
+        Assert.assertEquals(7, resources.size());
 
         // Test applications imported
         ClientModel application = realm.getClientByClientId("Application");
@@ -97,7 +97,7 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertNotNull(otherApp);
         Assert.assertNull(nonExisting);
         Map<String, ClientModel> clients = realm.getClientNameMap();
-        Assert.assertEquals(8, clients.size());
+        Assert.assertEquals(7, clients.size());
         Assert.assertTrue(clients.values().contains(application));
         Assert.assertTrue(clients.values().contains(otherApp));
         Assert.assertTrue(clients.values().contains(accountApp));