16

I'm using JWT with .Net Core 2.1, and the

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

decorator on my controller class. In 2.0 it seemed you had to do something like the following, but it's now marked as obsolete:

var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync("Bearer");
string accessToken = authenticateInfo.Properties.Items[".Token.access_token"];

I've seen some other fairly circuitous methods of extending authorisation classes and the like which I'd rather avoid. I simply want to access the particulars of the token much as I'd encoded them, eg the .Sub, and custom claims I've added like "Name" and "Roles". How to do so in .Net Core 2.1?

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
Glinkot
  • 2,924
  • 10
  • 42
  • 67

2 Answers2

27

Try casting HttpContext.User.Identity as ClaimsIdentity.

claimsIdentity = User.Identity as ClaimsIdentity;

// alternatively
// claimsIdentity = HttpContext.User.Identity as ClaimsIdentity;

// get some claim by type
var someClaim = claimsIdentity.FindFirst("some-claim");

// iterate all claims
foreach (var claim in claimsIdentity.Claims)
{
    System.Console.WriteLine(claim.Type + ":" + claim.Value);
}

Here are the .NET Core specific docs that support the HttpContext.User.Identity property.

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • Thanks. I can see something along those lines here (https://github.com/tjoudeh/AspNetIdentity.WebApi/blob/master/AspNetIdentity.WebApi/Controllers/ClaimsController.cs) and it looks like this is the older Asp.Net, not asp.net Core? I get an error that User does not contain a definition for Identity. – Glinkot Oct 02 '18 at 03:28
  • The .NET Core `User` will have an `Identity` property, because the `HttpContext.User` returns a `ClaimsPrincipal` which has an `Identity` property. I updated the answer with links to relevant .NET Core 2.1 docs. – Shaun Luttin Oct 02 '18 at 16:46
  • From my reading I don't believe this is the same for WebAPI. (eg https://stackoverflow.com/questions/19884619/is-it-possible-to-access-httpcontext-current-session-from-web-api). I really just want to get to the details in the bearer token in the request parameters rather than referring to a session type object. – Glinkot Oct 02 '18 at 22:53
  • 1
    The question that you referenced is using the full framework not Core. Note the mention of Web Forms and that the question is from 2013. It sounds like you are wanting to parse and read the Bearer token yourself. Most apps do not have a need for that; rather, most apps rely on the built-in ASP.NET Core middleware to validate/parse/read the Bearer token and surface its claims inside the `User` object. – Shaun Luttin Oct 02 '18 at 23:13
  • I thought I was very clear about wanting to do it in Core, but not to worry. – Glinkot Oct 02 '18 at 23:36
  • In case it helps someone. In .net core 2.2 web-API controller action method I use `User.Claims`, in my case `User.Claims.Where(c => c.Type == "AgentId").FirstOrDefault()?.Value` – Jonny Aug 08 '19 at 21:21
5

No need to cast, at least if you are using .Net Core 3.1. Simply access the values like this from a Controller:

var nameIdentifier = User.FindFirst(ClaimTypes.NameIdentifier);
var name = User.FindFirst(ClaimTypes.Name);
var givenName = User.FindFirst(ClaimTypes.GivenName);
var surname = User.FindFirst(ClaimTypes.Surname);
var email = User.FindFirst(ClaimTypes.Email);
var mobilePhone = User.FindFirst(ClaimTypes.MobilePhone);
var authenticationMethod = User.FindFirst(ClaimTypes.AuthenticationMethod);
var emails = User.FindFirst("emails");

From an access_token you can read values like this:

var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(adb2cTokenResponse.access_token);

var givenName = jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.GivenName).Value;
var familyName = jwtSecurityToken.Claims.First(claim => claim.Type == JwtRegisteredClaimNames.FamilyName).Value;
//Unless Alternate email have been added in Azure AD there will only be one email here. 
//TODO Handle multiple emails
var emails = jwtSecurityToken.Claims.First(claim => claim.Type == ADB2CJwtRegisteredClaimNames.Emails).Value;

public struct ADB2CJwtRegisteredClaimNames
{
    public const string Emails = "emails";

    public const string Name = "name";
}
Ogglas
  • 62,132
  • 37
  • 328
  • 418