Search code examples
c#.netasp.net-mvcasp.net-mvc-5asp.net-membership

Impersonate a user in a standard ASP.NET MVC installation template


I have setup a standard ASP.NET MVC site with normal authentication. I have added roles, so new users get a specific role.

Now, I want to be able to impersonate a user.

Impersonating advice

Impersonating, when I search around, comes the following way:

     FormsAuthentication.SetAuthCookie(user.UserName, false);

This doesn't work by default, as you have to do two things:

1:

Enable forms authentication:

 <system.web>
    <authentication mode="Forms" />
  </system.web>

2:

Disable the module:

<system.webServer>
    <modules>
      <!--<remove name="FormsAuthentication" />-->
    </modules>
    <staticContent>

The challenge

However, doing this leaves a couple of challenges.

  1. When you impersonate, you cannot log out. This is easily fixed by adding the following in LogOut: FormsAuthentication.SignOut();
  2. The User.IsInRole(Constants.Roles.Creditor); stops working, so we cannot check if user in a role

What to do?

This COULD boil down to me - apparently - not fully understanding the membership framework despite trying. However, how do you get impersonate to work here?

I have no explicit reason to use "Forms" authentication, and the only reason I started on this path is Impersonating. So I see I have two obvious directions:

  • A) Implement impersonation in a different way, so I don't touch my web.config to use forms
  • B) Fix the role problem in forms

Any help here? :-)


Solution

  • There are quite a few ways to accomplish this all you really need to do is get both the Id's to your controller and decide how you want it persisted (Cookie, Cache, Db , etc.).

    An easy way to do this is to create a claim for the impersonation and add a policy for those kind of claims. Here is a link for adding claim based policies.

    Here is some code to get you started :

    In your controllers you will want an end point that does something like this

            var claims = await UserManager.GetClaimsAsync(CurrentUserId);
            var claim = claims.FirstOrDefault(c => c.Type == "Impersonate");
            if (claim!=null)
            {
                //You may forget to remove it or the user could end there session before you are able to
                var r = await UserManager.RemoveClaimAsync(CurrentUserId, claim);
            }
            var result = await UserManager.AddClaimAsync(CurrentUserId, new Claim("Impersonate", userId));
    
            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }
    

    Now with the code above we wanted the users ID, but we could have just as easily gotten there role and saved that with the claim. From here you just need to decide how you want to use this claim. The link below will show you how you can do that.

    https://learn.microsoft.com/en-us/aspnet/core/security/authorization/claims

    Just remember to remove the claim after you are done.

    This one works nice when you may have to impersonate a user for sometime. One project I worked on the clients the needed to be able to impersonate users for weeks at a time to complete work for other clients.