123

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

Elrond_EGLDer
  • 47,430
  • 25
  • 189
  • 180
tcode
  • 4,787
  • 19
  • 59
  • 117
  • Can you confirm that the cookie is sent back by the browser? Maybe your security settings demand SSL? – leastprivilege Jan 29 '14 at 09:45
  • @leastprivilege Thanks, I'll look into that now. I found this question on Stackoverflow, http://stackoverflow.com/questions/20319118/i-cant-seem-to-get-a-very-basic-cookie-login-example-to-work-with-mvc5-and-owin?rq=1 it is the exact same problem I am having, but unfortunately no answer to it :( – tcode Jan 29 '14 at 14:42
  • How are your OWIN components initialized? – Derek Van Cuyk Aug 01 '14 at 19:01
  • I recently had a problem like this; I hope this solution helps: http://stackoverflow.com/questions/34537475/owin-identity-roles-work-locally-but-seem-to-disappear-when-i-publish-run-the-s/34548579#34548579 – Alexandru Dec 31 '15 at 15:44

12 Answers12

178

Try this:

[Authorize]
public ActionResult SomeAction()
{
    var identity = (ClaimsIdentity)User.Identity;
    IEnumerable<Claim> claims = identity.Claims;
    ...
}
Darin Dimitrov
  • 960,118
  • 257
  • 3,196
  • 2,876
  • 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. – tcode Jan 28 '14 at 14:28
  • No, sorry I don't have other ideas. This has always worked for me. – Darin Dimitrov Jan 28 '14 at 14:58
  • Sorry, one last question. Do I need to create my own custom ClaimsAuthenticationManager class and Application_PostAuthenticateRequest() in Global.asax like this http://dotnetcodr.com/2013/02/25/claims-based-authentication-in-mvc4-with-net4-5-c-part-1-claims-transformation/ before my code above will work? Thanks again. – tcode Jan 28 '14 at 17:27
  • 7
    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. – Adam Tuliper - MSFT Nov 24 '14 at 10:19
  • I'm working with asp.net core and looking for the way to get LinkedIn profile picture during more than 2 hours. I'm stuck, I'm tired, I want to give up until I see your answer. I want to say thanks million times... +1 –  Jul 21 '17 at 19:32
36

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);
Jay Stevens
  • 5,425
  • 8
  • 42
  • 67
hutchonoid
  • 31,459
  • 14
  • 91
  • 100
  • 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 http://dotnetcodr.com/2013/02/25/claims-based-authentication-in-mvc4-with-net4-5-c-part-1-claims-transformation/ before my code above will work? Thanks again for your help. – tcode Jan 28 '14 at 17:29
  • Hi, I will take a look when I'm back on a PC. – hutchonoid Jan 28 '14 at 17:40
  • thanks, really appreciate it. At a stage where this is starting to crack me up :) – tcode Jan 28 '14 at 17:42
  • @tgriffiths Hi, I've added an update for you. Hopefully providing a bit more info. Good luck. :) – hutchonoid Jan 28 '14 at 19:18
  • unfortunately I'm not using the built in Entity Framework Code First, e.g., UserManager etc. But thanks for your input. Cheers. – tcode Jan 28 '14 at 21:58
  • 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...http://dotnetcodr.com/2013/02/25/claims-based-authentication-in-mvc4-with-net4-5-c-part-1-claims-transformation/ – hutchonoid Jan 28 '14 at 22:03
  • any idea on how to add a claim when creating users via EF seed methods? – TWilly May 23 '16 at 01:27
32

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()
Rosdi Kasim
  • 20,195
  • 22
  • 115
  • 142
Jesus Padilla
  • 318
  • 3
  • 4
18

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();
    }
}
Quentin
  • 1,240
  • 15
  • 30
13

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;
Patrick
  • 16,618
  • 5
  • 65
  • 82
Eric Bridges
  • 135
  • 1
  • 6
10

You can also do this.

IEnumerable<Claim> claims = ClaimsPrincipal.Current.Claims;
Patrick
  • 16,618
  • 5
  • 65
  • 82
angularsen
  • 7,134
  • 1
  • 60
  • 76
8

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();
bummi
  • 26,435
  • 13
  • 58
  • 97
8

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;
Gwen
  • 1,254
  • 2
  • 20
  • 26
noman zafar
  • 81
  • 1
  • 4
6
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.

Basil Banbouk
  • 393
  • 4
  • 15
  • The `GenerateUserIdentityAsync` was an awesome suggestion, I have totally overlooked it. Thanks a lot Basil. – timmi4sa Jun 28 '14 at 01:20
2

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();
conterio
  • 869
  • 1
  • 9
  • 20
1
var claim = User.Claims.FirstOrDefault(c => c.Type == "claim type here");
Felipe Deveza
  • 1,549
  • 1
  • 15
  • 26
0

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();
    }
B M
  • 1,605
  • 1
  • 20
  • 37