[asp.net] MVC 5 Access Claims Identity User Data

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

The answer is


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();
    }
}

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);

shortest and simplified version of @Rosdi Kasim'd answer is

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity).
    FindFirst("claimname").Value;

Claimname is the claim you want to retrieve i.e if you are looking for "StreedAddress" claim then the above answer will be like this

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity).
    FindFirst("StreedAddress").Value;

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;

You can also do this.

IEnumerable<Claim> claims = ClaimsPrincipal.Current.Claims;

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()

Request.GetOwinContext().Authentication.User.Claims

However it is better to add the claims inside the "GenerateUserIdentityAsync" method, especially if regenerateIdentity in the Startup.Auth.cs is enabled.


var claim = User.Claims.FirstOrDefault(c => c.Type == "claim type here");

I used it like that in my base controller. Just sharing for ready to use.

    public string GetCurrentUserEmail() {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var email = claims.Where(c => c.Type == ClaimTypes.Email).ToList();
        return email[0].Value.ToString();
    }

    public string GetCurrentUserRole()
    {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var role = claims.Where(c => c.Type == ClaimTypes.Role).ToList();
        return role[0].Value.ToString();
    }

Remember that in order to query the IEnumerable you need to reference system.linq.
It will give you the extension object needed to do:

CaimsList.FirstOrDefault(x=>x.Type =="variableName").toString();

According to the ControllerBase class, you can get the claims for the user executing the action.

enter image description here

here's how you can do it in 1 line.

var claims = User.Claims.ToList();

Examples related to asp.net

RegisterStartupScript from code behind not working when Update Panel is used You must add a reference to assembly 'netstandard, Version=2.0.0.0 No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization How to use log4net in Asp.net core 2.0 Visual Studio 2017 error: Unable to start program, An operation is not legal in the current state How to create roles in ASP.NET Core and assign them to users? How to handle Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause() ASP.NET Core Web API Authentication Could not load file or assembly 'CrystalDecisions.ReportAppServer.CommLayer, Version=13.0.2000.0 WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for jquery

Examples related to asp.net-mvc

Using Lato fonts in my css (@font-face) Better solution without exluding fields from Binding Vue.js get selected option on @change You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to send json data in POST request using C# VS 2017 Metadata file '.dll could not be found The default XML namespace of the project must be the MSBuild XML namespace How to create roles in ASP.NET Core and assign them to users? The model item passed into the dictionary is of type .. but this dictionary requires a model item of type How to use npm with ASP.NET Core

Examples related to authentication

Set cookies for cross origin requests How Spring Security Filter Chain works What are the main differences between JWT and OAuth authentication? http post - how to send Authorization header? ASP.NET Core Web API Authentication Token based authentication in Web API without any user interface Custom Authentication in ASP.Net-Core Basic Authentication Using JavaScript Adding ASP.NET MVC5 Identity Authentication to an existing project LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1

Examples related to asp.net-mvc-5

'router-outlet' is not a known element The type or namespace name 'System' could not be found How to get 'System.Web.Http, Version=5.2.3.0? EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType How to extend available properties of User.Identity How to implement oauth2 server in ASP.NET MVC 5 and WEB API 2 How to get JSON object from Razor Model object in javascript The model backing the 'ApplicationDbContext' context has changed since the database was created How can I implement a theme from bootswatch or wrapbootstrap in an MVC 5 project? MVC 5 Access Claims Identity User Data

Examples related to claims-based-identity

MVC 5 Access Claims Identity User Data