Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use ASP.NET Identity 2.0 to allow a user to impersonate another user?

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?

like image 947
trailmax Avatar asked Jun 11 '14 11:06

trailmax


People also ask

How do I impersonate a user in C#?

To impersonate the IIS authenticating user on every request for every page in an ASP.NET application, we must include an <identity> tag in the Web. config file of this application and set the impersonate attribute to true.

How do I impersonate a user in web config?

In the application's Web. config file, set the impersonate attribute in the identity element to true. Set the NTFS access control list (ACL) for the ManagerInformation directory to allow access to only those identities that are in the Windows Manager group and any required system accounts.


1 Answers

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

like image 64
trailmax Avatar answered Oct 18 '22 06:10

trailmax