JWT Bearer ASP.Net Core 3.1 User is blank on server

Viewed 2197

Today I've been attempting to bind JSON Web Token info to the HttpContext.User using the Microsoft.AspNetCore.Authentication.JwtBearer library.

The Problem: Every time I make a call to the server, I'm able to get into functions with the [Authorize] attribute, but the User object is completely blank. It would be nice to know who each user is.

My decoded JWT on the client-side: decoded_jwt

My client-side function to call an [Authorize] C# method on the server:

testAuth() {
    let token = localStorage.getItem("jwt");
    console.log(this.jwtHelper.decodeToken(token)); // Where I got the decoded JWT picture
    this.http.get(this.baseUrl + "Authentication/Test", {
      headers: new HttpHeaders({
        "Content-Type": "application/json",
        "Authentication": "Bearer " + token
      })
    }).subscribe(response => {
      console.log(response); // never happens
    }, err => {
      console.log(err); // always happens because User.Identity is null
    });
  }

The server method where User.Identity is always blank, but we are allowed through the [Authorize] attribute:

[HttpGet]
[Authorize]
public IActionResult Test()
{
    // User.Identity is always blank, so a 500 error is thrown because Name == null
    return Ok(HttpContext.User.Identity.Name);
}

Middleware pipeline: ConfigureServices() in Startup.cs:

services.AddControllers();

            // Enable CORS (cross origin requests) so other sites can send requests to the auth API
            services.AddCors();

            // JWT
            // Use JSON Web Tokens for auth
            services.AddAuthentication(opt => {
                opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = true,
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = false,
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration.GetValue<string>("JwtInfo:SecretKey"))),
                    ValidIssuer = Configuration.GetValue<string>("JwtInfo:ServerAddress", "http://localhost:44351/"), // Address that this project is running on
                    ValidAudience = Configuration.GetValue<string>("JwtInfo:ValidRecipients", "http://localhost:44364/") // Addresses of projects that are allowed to access this API
                };
            });

Configure() in Startup.cs:

app.UseHttpsRedirection();

            app.UseRouting();

            // Allow CORS (cross origin requests)
            // This must come before routing, authentication, and endpoints
            app.UseCors(option => option
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader());

            // Use JWT authentication
            app.UseAuthentication();
            app.UseAuthorization();

How do I correctly bind the JWT claims to the User's claims?

How am I getting through [Authorize] if the User is blank?

Your help is appreciated!

3 Answers

The header containing the token was set incorrectly. It should be:

"Authorization": "Bearer " + token

Instead of "Authentication": "Bearer " + token

I had this issue with an application that was developed with Asp.net Core and angular. The solution that worked for me is to set in client side (angular) allowedDomains: ["ServerAdress:port"], in app.module

enter image description here

You need to use IHttpContextAccessor and register the dependency in the configure services method.

Step 1- register the dependency

services.AddHttpContextAccessor();

Step 2 - inject the dependency in the constructor of the controller or wherever you require

private readonly IHttpContextAccessor _httpContextAccessor;

public MyController(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}

Step 3 - use the code below to get user info var user = _httpContextAccessor.HttpContext.User.Identity;

From the ms documentation:

For other framework and custom components that require access to HttpContext, the recommended approach is to register a dependency using the built-in dependency injection container. The dependency injection container supplies the IHttpContextAccessor to any classes that declare it as a dependency in their constructors:

Here, is the official Microsoft documentation, please go through it to get more details:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context

Related