42

I'm migrating a ASP.NET MVC 5.1 application from MembershipProvider to ASP.NET Identity v2.0. One of the features I have in the application is user impersonation: Administrators can be logged in as any other user registered on the site without knowing passwords.

I used this code to implement user impersonation for the MembershipProvider and this does not work with Identity library.

How do I implement user impersonation (not IIS impersonation) in ASP.NET Identity?

1
  • A question looking for off-site resources is off-topic. I've edited your question to allow for answers that are on-topic, and it still achieves the same ends. Commented Jun 11, 2014 at 11:55

2 Answers 2

66

I've found a solution to this problem.

Basically I add claim with admin username, if this claim exists, I know that impersonation is happening. When admin wants to stop impersonation, system retrieves original username for the claims, deletes old impersonated-cookie and creates a new cookie for the admin:

[AuthenticateAdmin] // <- make sure this endpoint is only available to admins public async Task ImpersonateUserAsync(string userName) { var context = HttpContext.Current; var originalUsername = context.User.Identity.Name; var impersonatedUser = await userManager.FindByNameAsync(userName); var impersonatedIdentity = await userManager.CreateIdentityAsync(impersonatedUser, DefaultAuthenticationTypes.ApplicationCookie); impersonatedIdentity.AddClaim(new Claim("UserImpersonation", "true")); impersonatedIdentity.AddClaim(new Claim("OriginalUsername", originalUsername)); var authenticationManager = context.GetOwinContext().Authentication; authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, impersonatedIdentity); } 

More information is in my blog-post: User impersonation with ASP.Net Identity 2.

User Impersonation in Asp.Net Core

Upd July 2017: this topic is quite popular, so I've looked into user impersonation in Core and principles are very similar with updated API. Here is how to impersonate:

 [Authorize(Roles = "Admin")] // <-- Make sure only admins can access this public async Task<IActionResult> ImpersonateUser(String userId) { var currentUserId = User.GetUserId(); var impersonatedUser = await _userManager.FindByIdAsync(userId); var userPrincipal = await _signInManager.CreateUserPrincipalAsync(impersonatedUser); userPrincipal.Identities.First().AddClaim(new Claim("OriginalUserId", currentUserId)); userPrincipal.Identities.First().AddClaim(new Claim("IsImpersonating", "true")); // sign out the current user await _signInManager.SignOutAsync(); // If you use asp.net core 1.0 await HttpContext.Authentication.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal); // If you use asp.net core 2.0 (the line above is deprecated) await HttpContext.SignInAsync(cookieOptions.ApplicationCookieAuthenticationScheme, userPrincipal); return RedirectToAction("Index", "Home"); } 

This is how to stop impersonation:

 [Authorize(Roles = "Admin")] // <-- Make sure only admins can access this public async Task<IActionResult> StopImpersonation() { if (!User.IsImpersonating()) { throw new Exception("You are not impersonating now. Can't stop impersonation"); } var originalUserId = User.FindFirst("OriginalUserId").Value; var originalUser = await _userManager.FindByIdAsync(originalUserId); await _signInManager.SignOutAsync(); await _signInManager.SignInAsync(originalUser, isPersistent: true); return RedirectToAction("Index", "Home"); } 

Full explanation in my blog: http://tech.trailmax.info/2017/07/user-impersonation-in-asp-net-core/ Full code sample on GitHub: https://github.com/trailmax/AspNetCoreImpersonation

Sign up to request clarification or add additional context in comments.

11 Comments

Awesome work. It seems like the implementation of SecurityStampValidator has been updated to be culture-aware, so there is a bit more complexity to creating a modified version of this class as it has internal dependencies that also now need to be cribbed (surprised at the non-extensible nature of it TBH). Easy enough. Works really well.
@spender do you mean it has been updated in v3? I see last update to v2 branch was in April 2015
Hi @trailmax In nuget package Microsoft.AspNet.Identity.Owin version 2.2.1, there are several calls from SecurityStampValidator to an extension method Microsoft.AspNet.Identity.TaskExtensions.WithCurrentCulture<T>. Because the TaskExtensions class is internal (i.e. not visible from my assembly), it means I had to copy that over too to get it to work.
@spender huh.. I guess I've missed that somehow... or ignored.
You're a ledge mate
|
-2

Just for who is using the Asp Net Core Identity, this is the code to solve the initial problem (An Administrator that want to enter as user, without knowing password). The following solution is not a real "Impersonation" with token as in the voted answer :

 [Authorize("Administrator")] public async Task<IActionResult> ImpersonateUserAsync(string email) { var impersonatedUser = await _userManager.FindByNameAsync(email); //Usually username is the email await _signInManager.SignOutAsync(); //signout admin await _signInManager.SignInAsync(impersonatedUser,false); //Impersonate User return RedirectToAction("Index","Home"); } 

4 Comments

This isn't impersonation, it's just signing in as a different user. For real impersonation, you need to remain logged in as the original user.
Ok, David, it's true. But the first question of Trailamx was:"Administrators can be logged in as any other user registered on the site without knowing passwords" . With the method above, decorated, for example, by [Authorize("Administrator")] using Asp.Net Identity, you solved the original problem, in Asp.Net Core . Note that "Administrator" in the Authorize statement must be a role configured in Asp.Net Identity System Table .
Yes, it's still a bit of a hack though, that's my real issue with it. You would also be forced to log back in as the admin once you've done whatever you need to do as the impersonated user. That's what makes this method not particularly viable for me.
@GiulioFronterotta see my updated answer for impersonation in Core

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.