Search code examples
c#asp.net-coreauthenticationjwt.net-8.0

Not all claims from JWT reflected in user's identity


I'm adding a bearer token that I copied from an application to the request to my API. In that token, I see the claim "sub" (among several other). Then, in the controller, as I inspect the claims for the identity of my user, I see some - but not all - of them. Subject is gone, names are gone, roles are gone etc.

According to this answer, I need replace a call to Clear() in my handler. The thing is that I have no handler and no code to clear needs to be upgraded. I also tried requiring security tokens as suggested at MSDN for breaking changes, with no luck.

How can I get the missing claims into my user's claims?

builder.Services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(opt =>
  {
    opt.Authority = "https://sts.windows.net/a2728528-...-7d900c45d9ba/";
    opt.TokenValidationParameters.ValidateAudience = false;
    opt.TokenValidationParameters.ValidateLifetime = false;
    //opt.UseSecurityTokenValidators = true;
  });
//builder.Services.AddAuthorization();
...
app.UseAuthentication();
app.UseAuthorization();

After some googling I've found something from 2016, so probably not even related (despite the shallow resemblance). Naturally, as expected, the following alteration didn't change anything - the claims in the user's identity in the HTTP context on the controller still miss a few items from the JWT.

builder.Services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(opt =>
  {
    ...
    opt.TokenValidationParameters.NameClaimType = "sub";
    opt.TokenValidationParameters.RoleClaimType = "role";
  });

Solution

  • How can I get the missing claims into my user's claims?

    Well, By default, ASP.NET Core maps specific JWT claims to properties on the ClaimsPrincipal object (user's identity). "sub" is typically mapped to ClaimsPrincipal.Name

    If the token contains custom claims (e.g., "name," "roles") for user information, these won't be automatically mapped without proper configuration.

    In this scenario, you could try refactoring the following code:

    You could set NameClaimType and RoleClaimType in your TokenValidationParameters

    opt.TokenValidationParameters.NameClaimType = "name";
    opt.TokenValidationParameters.RoleClaimType = "role";
    

    Note: Above modification would ensure your API looks for the specific claim names used by the issuing application.

    Now, you can directly access claims directly from the ClaimsPrincipal. So, you could do like following:

    var claims = User.Claims;
    string name = claims.FirstOrDefault(c => c.Type == "name")?.Value;
    IEnumerable<string> roles = claims.Where(c => c.Type == "role").Select(c => c.Value);
    

    Note: In addition, If you're using custom claims transformation, ensure that it's not inadvertently removing or modifying the claims. Please refer to this official document that might be resoruceful.