2

I am trying to access a user's claims from his Bearer token in ASP.NET Core, but in the handler, HttpContext.User.Identity.Name is always null, and the Claims collection is empty.

The token is passed as a header like this:

Authorization: Bearer eyJhbGci....

In Startup.Configure I call UseAuthentication after UseRouting and before UseEndpoints.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseAuthentication();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync(context.User.Identity.Name ?? "null");
        });
    });
}

In Startup.ConfigureServices I call AddAuthentication and AddJwtBearer. I added a bunch of options to try and disable as much validation as I could, as I'm just trying to read the values from the token for now, but that didn't help.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => 
        {
            options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters {
                ValidateIssuer = false,
                ValidateIssuerSigningKey = false,
                ValidateAudience = false,
                ValidateActor = false,
                ValidateLifetime = false,
                ValidateTokenReplay = false,
            };
        }
    );
}

My token is a default dummy one from https://jwt.io/#debugger-io and it looks like this when decoded:

{"alg":"HS256","typ":"JWT"}{"sub":"1234567890","name":"John Doe","iat":1516239022}

What am I missing for this to work?

Asik
  • 21,506
  • 6
  • 72
  • 131
  • 1
    Have you ever set a break point or use F12 developer tools to check the response, do you meet the 401 error? I checked your JWT configuration and the Token, it will show the 401 error on my side, but if I generate the JWT token with the Issuer and SigningKey (check [this screenshot](https://i.stack.imgur.com/IhBTo.png)), and change the JWT configuration [like this](https://i.stack.imgur.com/Yr5lB.png), I could get the user information from the HttpContext. So, you could try to use this method. – Zhi Lv May 20 '21 at 07:55
  • @Asik - did you ever figure out what was going on here? – Noelle Caldwell Aug 03 '23 at 05:22

4 Answers4

1

By default Name claim type maps to UniqueName, you need to change it's mapping.

.AddJwtBearer(o => o.TokenValidationParameters = new TokenValidationParameters
{
    NameClaimType = "name"
})

Please refer this question: I can Authenticate with my JWT but my Name claim is not recognised in my ASP.NET Core application

honey_ramgarhia
  • 537
  • 7
  • 15
  • 1
    That's a good point, thanks. However, I just don't have any claims (the `Claims` collections is empty like I mentioned), so it's not just a mapping problem. – Asik May 17 '21 at 18:37
  • 1
    But JWT token contains a name claim `{"alg":"HS256","typ":"JWT"}{"sub":"1234567890","name":"John Doe","iat":1516239022}`, so I thought you must've included it. Could you try adding a name claim and also updating the NameClaimType setting. – honey_ramgarhia May 17 '21 at 18:42
  • Yeah, I added the code you provided, but my `Claims` collection is still empty (on `context.User.Claims` or `context.User.Identity.Claims`). It seems like ASP.NET is giving me a default empty identity and not including anything from the JWT token. – Asik May 17 '21 at 18:46
  • Can you update the question and add token generation code? – honey_ramgarhia May 17 '21 at 18:52
  • Like I mentioned in the question, I just copy-pasted the dummy one from https://jwt.io/#debugger-io . – Asik May 17 '21 at 18:56
0

This is what I use to get the user name from JWT:

public class Helper
{
    /// <summary>
    /// Retrieve name of the user executing the request.
    /// </summary>
    /// <param name="user">User info.</param>
    /// <returns>User name.</returns>
    internal static string GetUserName(ClaimsPrincipal user)
    {
        return user.Claims
            .FirstOrDefault(c => c.Type == ClaimTypes.Name || c.Type == "name")
            .Value;
    }
}

and call that like this:

Helper.GetUserName(HttpContext.User);

link to my repo containing above code

  • 1
    Thanks, but my `Claims` collections is empty like I mentioned, so `FirstOrDefault` would return null. – Asik May 17 '21 at 18:36
  • Sorry, didn't notice that. I think the real problem is that the Claims is empty. Not sure why, maybe you could try use https://demo.identityserver.io/ as your auth server? – Martinus Suherman May 17 '21 at 18:55
  • Maybe you can see this: https://stackoverflow.com/questions/53237854/asp-net-core-jwt-login-not-setting-httpcontext-user-claims seems like the same problem you experience – Martinus Suherman May 17 '21 at 19:06
  • Maybe you can read the name directly from the token as described here: https://stackoverflow.com/questions/57959822/get-jwt-claims-directly-from-the-token-asp-net-core-2-1 – Martinus Suherman May 18 '21 at 14:40
0

Try this:

 services
        .AddControllers(options =>
        {
            options.Filters.Add(new AuthorizeFilter());
        });

Then:

 app.UseAuthentication();
 app.UseAuthorization(); 

and it must work.

feihoa
  • 477
  • 4
  • 10
0

You should add UseAuthorization() middleware after UseAuthentication() middleware

app.UseAuthentication();
app.UseAuthorization();

Your `Configure' method should be like this

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync(context.User.Identity.Name ?? "null");
        });
    });
}
Farhad Zamani
  • 5,381
  • 2
  • 16
  • 41
  • That's something I had tried before, but no luck. I'm not sure how this problem might relate to authorization. – Asik May 17 '21 at 18:39