> GetUser() { var token = HttpContext.Request.Headers["Authorization"].FirstOr" /> > GetUser() { var token = HttpContext.Request.Headers["Authorization"].FirstOr" /> > GetUser() { var token = HttpContext.Request.Headers["Authorization"].FirstOr"/>

.NET httpContext showing null claims

104 views Asked by At
[Authorize]
[HttpGet("getUser")]
public async Task<ActionResult<UserDTO>> GetUser()
{
    
        var token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
        if (string.IsNullOrEmpty(token))
        {
            return Unauthorized(new { message = "Token is required." });
        }

        var handler = new JwtSecurityTokenHandler();
        if (!handler.CanReadToken(token))
        {
            return BadRequest(new { message = "Invalid token format." });
        }

        var jwtToken = handler.ReadJwtToken(token);
        var claims = jwtToken.Claims;

        
        
        var email = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.Email);
        
        var result = await Mediator.Send(new GetUser.Command());
        return HandleResults(result);
    
}

Ok so I was creating a way to persist login and had some issues with the claims being null. It seems like the token does have the claims, when inspecting it in debug mode I see It has 6 but when trying to access the claim with the httpcontext it just returns null.

This is my token generating code

public string Token(ApplicationUser user)
{
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, user.UserName),
        new Claim(ClaimTypes.NameIdentifier, user.Id),
        new Claim(ClaimTypes.Email, user.Email),
    };


    var jwtKey = _configuration["JwtConfig:Key"];
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddDays(1),
        SigningCredentials = creds
    };

    var tokenHandler = new JwtSecurityTokenHandler();
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

private TokenValidationParameters GetValidationParameters()
{
    return new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtConfig:Key"])),
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero
    };
}

I tried adding an authentication scheme which didnt work

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = key,
            ValidateIssuer = false,
            ValidateAudience = false,
        };
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];
                if (!string.IsNullOrEmpty(accessToken) &&
                    (context.HttpContext.WebSockets.IsWebSocketRequest || context.Request.Headers["Accept"] == "text/event-stream"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {

                System.Console.WriteLine(context.Exception);
                return Task.CompletedTask;
            },
        };
    });

I also made sure to use the Authorization tag and have authentication ahead of authorization, still no success. Any help would be appreciated.

1

There are 1 answers

1
Alex On BEST ANSWER

If your endpoint is correctly authenticated with JWT, then you don't need to get the token from the HttpContext.Request object.

First, you need to replace the endpoint Authorize attribute with the following:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Then make sure you have the correct claims in the token that will then be used to protect the endpoint.

The following can be removed, as the underlying framework will take care of it for you:

    var token = HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
    if (string.IsNullOrEmpty(token))
    {
        return Unauthorized(new { message = "Token is required." });
    }

    var handler = new JwtSecurityTokenHandler();
    if (!handler.CanReadToken(token))
    {
        return BadRequest(new { message = "Invalid token format." });
    }

    var jwtToken = handler.ReadJwtToken(token);
    var claims = jwtToken.Claims;