MVC 5 Access Claims Identity User Data
Solution 1
Try this:
[Authorize]
public ActionResult SomeAction()
{
var identity = (ClaimsIdentity)User.Identity;
IEnumerable<Claim> claims = identity.Claims;
...
}
Solution 2
You can also do this:
//Get the current claims principal
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
var claims = identity.Claims;
Update
To provide further explanation as per comments.
If you are creating users within your system as follows:
UserManager<applicationuser> userManager = new UserManager<applicationuser>(new UserStore<applicationuser>(new SecurityContext()));
ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
You should automatically have some Claims populated relating to you Identity.
To add customized claims after a user authenticates you can do this as follows:
var user = userManager.Find(userName, password);
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
The claims can be read back out as Darin has answered above or as I have.
The claims are persisted when you call below passing the identity in:
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = persistCookie }, identity);
Solution 3
I make my own extended class to see what I need, so when I need into my controller or my View, I only add the using to my namespace something like this:
public static class UserExtended
{
public static string GetFullName(this IPrincipal user)
{
var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.Name);
return claim == null ? null : claim.Value;
}
public static string GetAddress(this IPrincipal user)
{
var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.StreetAddress);
return claim == null ? null : claim.Value;
}
public ....
{
.....
}
}
In my controller:
using XXX.CodeHelpers.Extended;
var claimAddress = User.GetAddress();
In my razor:
@using DinexWebSeller.CodeHelpers.Extended;
@User.GetFullName()
Solution 4
This is an alternative if you don't want to use claims all the time. Take a look at this tutorial by Ben Foster.
public class AppUser : ClaimsPrincipal
{
public AppUser(ClaimsPrincipal principal)
: base(principal)
{
}
public string Name
{
get
{
return this.FindFirst(ClaimTypes.Name).Value;
}
}
}
Then you can add a base controller.
public abstract class AppController : Controller
{
public AppUser CurrentUser
{
get
{
return new AppUser(this.User as ClaimsPrincipal);
}
}
}
In you controller, you would do:
public class HomeController : AppController
{
public ActionResult Index()
{
ViewBag.Name = CurrentUser.Name;
return View();
}
}
Solution 5
To further touch on Darin's answer, you can get to your specific claims by using the FindFirst method:
var identity = (ClaimsIdentity)User.Identity;
var role = identity.FindFirst(ClaimTypes.Role).Value;
tcode
Updated on November 08, 2020Comments
-
tcode over 3 years
I am developing an MVC 5 web application using Entity Framework 5 Database First approach. I am using OWIN for the authentication of Users. Below shows my Login method within my Account Controller.
public ActionResult Login(LoginViewModel model, string returnUrl) { if (ModelState.IsValid) { var user = _AccountService.VerifyPassword(model.UserName, model.Password, false); if (user != null) { var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, model.UserName), }, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role); identity.AddClaim(new Claim(ClaimTypes.Role, "guest")); identity.AddClaim(new Claim(ClaimTypes.GivenName, "A Person")); identity.AddClaim(new Claim(ClaimTypes.Sid, user.userID)); //OK to store userID here? AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = model.RememberMe }, identity); return RedirectToAction("Index", "MyDashboard"); } else { ModelState.AddModelError("", "Invalid username or password."); } } // If we got this far, something failed, redisplay form return View(model); }
As you can see I'm creating a ClaimsIdentity and adding several claims to it, then passing it to OWIN using the AuthenticationManager to perform the sign in.
The problem I am having is that I'm not sure how to access the claims in the rest of my application, either in Controllers or in Razor Views.
I had tried the approach listed in this tutorial
For example, I tried this in my Controller code in an attempt to get access to the values passed into the Claims, however, the user.Claims is equal to null
var ctx = HttpContext.GetOwinContext(); ClaimsPrincipal user = ctx.Authentication.User; IEnumerable<Claim> claims = user.Claims;
Perhaps I am missing something here.
UPDATE
Based on Darin's answer, I added his code but still I fail to see access to the Claims. Please see screenshot below showing what I see when hovered over identity.Claims.
-
tcode over 10 yearsThanks for your help. I used your suggested answer in an Action within a Controller to try and access the Claims values, however, I identity.Claims is still NULL (see updated question with screenshot). Any other ideas? I appreciate your help.
-
Darin Dimitrov over 10 yearsNo, sorry I don't have other ideas. This has always worked for me.
-
tcode over 10 yearsSorry, one last question. Do I need to create my own custom ClaimsAuthenticationManager class and Application_PostAuthenticateRequest() in Global.asax like this dotnetcodr.com/2013/02/25/… before my code above will work? Thanks again.
-
tcode over 10 yearsThanks, but still this doesn't work for me. Can you see my updated question? Also, one last question. Do I need to create my own custom ClaimsAuthenticationManager class and Application_PostAuthenticateRequest() in Global.asax like this dotnetcodr.com/2013/02/25/… before my code above will work? Thanks again for your help.
-
hutchonoid over 10 years@tgriffiths Hi, I've added an update for you. Hopefully providing a bit more info. Good luck. :)
-
tcode over 10 yearsunfortunately I'm not using the built in Entity Framework Code First, e.g., UserManager etc. But thanks for your input. Cheers.
-
hutchonoid over 10 yearsOh, right. Ok, you might be able to do it similar to how I've done it in MVC 4 then but I've not tried it in mvc5. This was a very good article that I used...dotnetcodr.com/2013/02/25/…
-
timmi4sa almost 10 yearsThe
GenerateUserIdentityAsync
was an awesome suggestion, I have totally overlooked it. Thanks a lot Basil. -
Adam Tuliper over 9 yearsUntil you Authorize for the first time, you wont have access to this until after your login method which is why the OP doesn't see it at that time. You have to load manually at this time if you want it in the Login method.
-
Juan Carlos Puerto over 8 yearsOr this one too string myValue = identity.FindFirstValue("MyClaimType");
-
TWilly about 8 yearsany idea on how to add a claim when creating users via EF seed methods?
-
Halter over 7 years
return claim?.Value;
because why not -
Phil about 5 yearsWhat happens if FindFirst does not find any claims with the "role" type? null exception?
-
FreeClimb over 3 yearsvar username = identity.FindFirst(ClaimTypes.NameIdentifier).Value;