MVC 5 Access Claims Identity User Data

218,236

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;
Share:
218,236
tcode
Author by

tcode

Updated on November 08, 2020

Comments

  • tcode
    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

    http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/

    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.

    enter image description here

  • tcode
    tcode over 10 years
    Thanks 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
    Darin Dimitrov over 10 years
    No, sorry I don't have other ideas. This has always worked for me.
  • tcode
    tcode over 10 years
    Sorry, 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
    tcode over 10 years
    Thanks, 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
    hutchonoid over 10 years
    @tgriffiths Hi, I've added an update for you. Hopefully providing a bit more info. Good luck. :)
  • tcode
    tcode over 10 years
    unfortunately I'm not using the built in Entity Framework Code First, e.g., UserManager etc. But thanks for your input. Cheers.
  • hutchonoid
    hutchonoid over 10 years
    Oh, 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
    timmi4sa almost 10 years
    The GenerateUserIdentityAsync was an awesome suggestion, I have totally overlooked it. Thanks a lot Basil.
  • Adam Tuliper
    Adam Tuliper over 9 years
    Until 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
    Juan Carlos Puerto over 8 years
    Or this one too string myValue = identity.FindFirstValue("MyClaimType");
  • TWilly
    TWilly about 8 years
    any idea on how to add a claim when creating users via EF seed methods?
  • Halter
    Halter over 7 years
    return claim?.Value; because why not
  • Phil
    Phil about 5 years
    What happens if FindFirst does not find any claims with the "role" type? null exception?
  • FreeClimb
    FreeClimb over 3 years
    var username = identity.FindFirst(ClaimTypes.NameIdentifier).Value;