I am replacing the (HttpContext.Current.User) IPrincipal with a custom version so I can store more information login and the user. I have done this before using the FormsAu
There are Claims that serve exactly the same purpose. Only new API is actually purposed this way.
Claims are a basically a Dictionary<String, String>
that is stored in auth-cookie and available through IPrincipal
. But you don't need to do ICustomPrincipal
because actual object that you get behind IPrincipal
is ClaimsPrincipal
and that has a list of claims.
You'd add extra information to Idnentity object just before the login:
public async override Task CreateIdentityAsync(ApplicationUser applicationUser)
{
var identity = await base.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim("MyApp:FullName", applicationUser.FullName));
return identity;
}
And then you'd be able to get this data out from IPrincipal via extension:
public static String GetFullName(this IPrincipal principal)
{
var claimsPrincipal = principal as ClaimsPrincipal;
if (claimsPrincipal == null)
{
throw new Exception("User is not logged in!");
}
var nameClaim = principal.Claims.FirstOrDefault(c => c.Type == "MyApp:FullName");
if (nameClaim != null)
{
return nameClaim.Value;
}
return String.Empty;
}
I have used this method successfully in a few projects already. See other similar answers for more code samples.
Here is another article, though I discourage from using Thread.CurrentPrincipal
or ClaimsPrincipal.Current
in MVC application - you don't always get what you expect, especially when user is not logged in or on early stages of AppPool start up.
This approach works for me (Using MVC4), slightly different from above.
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim("MyApp:OrganizationId", OrganizationID.ToString()));
return userIdentity;
}
public int OrganizationID { get; set; }
}
Extension method. Note you should use claimsPrincipal variable (instead of principal variable) to obtain the claims. I think that's a little mistake in the excelent answer of @trailmax (sorry for not comment this in your answer, my reputation doesn't allow me). Also, I use IIdentity instead of IPrincipal
public static class IdentityExtensions
{
public static int GetOrganizationId(this IIdentity principal)
{
var claimsPrincipal = principal as ClaimsIdentity;
if (claimsPrincipal == null)
{
throw new Exception("User is not logged in!");
}
var nameClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "MyApp:OrganizationId");
if (nameClaim != null)
{
return int.Parse(nameClaim.Value);
}
throw new Exception("ID doesn't exists");
}
}
And then, I use the extension method in the controller like this:
var organizationId = User.Identity.GetOrganizationId();
Hope this is useful to someone.