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.
FormsAuthentication.SignOut();
User.IsInRole(Constants.Roles.Creditor);
stops working, so
we cannot check if user in a roleWhat 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:
Any help here? :-)
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://docs.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.
If we need to implement the IsInRole()
method in basic forms principal, we need to customize the principal.
User
is a principal object, which contains list of Identities
. Default
identity does not contain role property, so we need to create custom identity object.
For e.g:
public class CustomPricipal : IPrincipal
{
public CustomPricipal(string username)
{
this.Identity = new CustomIdentity(username);
}
public IIdentity Identity
{
get;
private set;
}
public bool IsInRole(string role)
{
return this.Identity != null && ((CustomIdentity)this.Identity).Roles.Any(x => x.ToLower() == role.ToLower());
}
}
public class CustomIdentity : IIdentity
{
public CustomIdentity(string name)
{
// We can fetch the user information from database and create custom properties
this.Name = name;
this.IsAuthenticated = true;
this.AuthenticationType = "Forms";
this.Roles = new List<string>() { "Admin", "SuperAdmin" };
}
public string AuthenticationType
{
get;
private set;
}
public bool IsAuthenticated
{
get;
private set;
}
public string Name
{
get;
private set;
}
public List<string> Roles
{
get;
private set;
}
}
In global.asax.cs
public override void Init()
{
this.PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest;
base.Init();
}
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
Context.User = Thread.CurrentPrincipal = new CustomPricipal(authTicket.Name);
}
}
}
Now we can use the User.IsInRole("")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With