ASP.NET Core JWT authentication changes Claims (sub)
Asked Answered
D

2

11

I have an ASP.NET Core API which uses JWT Authentication. Simple setup:

....
string authority = $"https://{configuration["Auth:Authority"]}";
string audience = configuration["Auth:Audience"];

return builder.AddJwtBearer(options =>
{
    options.Authority = authority;
    options.Audience = audience;

    options.TokenValidationParameters = new TokenValidationParameters
    {
        // NameClaimType = "http://schemas.org/email"
        // NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email"
        // NameClaimType = "sub"
    };
});

(as you can see commented code, I have been trying several settings)

When I decode JWT (using jwt.io) I see there is claim "sub" in JWT and has string value (internal ID of user in dbo)

{
  "nbf": 1592585433,
  "exp": 1592585763,
  "iss": "https://*************",
  "aud": "api_10",
  "sub": "142",
  "scope": [
    "openid",
    "api_10"
  ]
}

The problem is that dotnet switch sub to name claim. This returns no (0) results:

principal.Claims.Where(w => w.Type == "sub")

This returns userId I need "142":

principal.Claims.Where(w => w.Type == ClaimTypes.Name || ClaimTypes.NameIdentifier)

What is going on?! Where is my sub claim gone?

Dumpcart answered 19/6, 2020 at 16:56 Comment(1)
You probably need the line JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();. Please please read this article for more explanation.Categorize
D
25

Just add either JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); (if you're on .NET 7 or earlier) or JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear(); (for .NET 8 or later) on the API's ConfigureServices method. Its suggested on the other comment as well. I verified it on my sample repo.

This issue is because OIDC StandardClaims are renamed on JWT token handler. By adding JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); you will clear the inbound claim type map on the JWT token handler.

Read more here

Dagda answered 19/6, 2020 at 19:40 Comment(4)
Also, this will fix it. https://mcmap.net/q/1013818/-httpcontext-user-claims-doesnt-match-jwt-token-quot-sub-quot-changes-to-quot-nameidentifier-quotMalign
Just had this same issue myself. Many thanks for the question and solution.Beaudoin
This no longer works in .NET 8. Haven't been able to verify why exactly...Henna
In .NET 8 it has changed to "JsonWebTokenHandler.DefaultInboundClaimTypeMap" and you need "using Microsoft.IdentityModel.JsonWebTokens" to bring it into scope.Dis
L
4

In .NET 8 you simply set the MapInboundOptions field of the JwtBearerOptions to false.

For Example:

services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(o => {
    o.MapInboundClaims = false;
    …
  }
Luxury answered 18/1 at 3:52 Comment(3)
This did not work for me. I had to add JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear(); in ConfigureServices as described in @Dagda 's answer.Foliar
I wonder if they are being set elsewhere in your startup sequence which is causing the need to clear them 🤷?Luxury
If it is, it's something subtle. There is no direct reference to MapInboundOptions I can also verify that the Clear() statement is the only reference to JsonWebTokenHandler in my app. So why the Clear() is necessary is still a mystery.Foliar

© 2022 - 2024 — McMap. All rights reserved.