I am in a strange situation with my .NET 7 web app. According to my application logs, my token is not found but still validated in some way which does not make sense to me. Hopefully, someone can explain and help me getting my controller method called. I used this web page to understand JWT Authentication in .NET 7.
I have the following code in my Program.cs:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddAuthentication(cfg => {
cfg.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
cfg.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
cfg.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("UwSuperGeheimeSleutelDieLangGenoegIs12345678")
),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
Console.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
},
OnMessageReceived = context =>
{
Console.WriteLine("OnMessageReceived: " + context.Token);
if (string.IsNullOrEmpty(context.Token))
{
Console.WriteLine("Token is missing from the request.");
}
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
Console.WriteLine("OnTokenValidated: " + context.SecurityToken);
return Task.CompletedTask;
},
OnChallenge = context =>
{
Console.WriteLine("OnChallenge: " + context.Error + " - " + context.ErrorDescription);
return Task.CompletedTask;
}
};
});
var token = TokenGenerator.GenerateJWTToken("Daan", Guid.NewGuid());
Console.WriteLine("TOKEN START");
Console.WriteLine(token);
Console.WriteLine("TOKEN END");
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseAuthentication();
app.MapControllers();
app.Run();
}
}
I have the following controller method:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet("checkclaims")]
[Authorize]
public IActionResult CheckClaims()
{
throw new NotImplementedException("Not yet implemented");
}
}
And this is my token generation:
public static class TokenGenerator
{
public static string GenerateJWTToken(string userName, Guid id)
{
var claims = new List<Claim> {
new Claim(ClaimTypes.NameIdentifier, id.ToString()),
new Claim(ClaimTypes.Name, userName),
};
var jwtToken = new JwtSecurityToken(
claims: claims,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddDays(30),
signingCredentials: new SigningCredentials(
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("UwSuperGeheimeSleutelDieLangGenoegIs12345678")
),
SecurityAlgorithms.HmacSha256Signature)
);
return new JwtSecurityTokenHandler().WriteToken(jwtToken);
}
}
I try to call my web api like this in VSCode REST Client
GET https://localhost:7126/api/Values/checkclaims
Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6ImVhZGRjYTdmLTBkYTMtNGU1Yy1iYzdkLThhM2Y3OWJmODg1ZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJEYWFuIiwibmJmIjoxNzE3Njg1Nzk4LCJleHAiOjE3MjAyNzc3OTh9.Jwp70J6IfHHvkrG0uu0dXrBxHcRBNthhKzkTMW6wNjo
And this is my response of my application:
HTTP/1.1 401 Unauthorized
Content-Length: 0
Connection: close
Date: Thu, 06 Jun 2024 14:57:20 GMT
Server: Kestrel
WWW-Authenticate: Bearer
With this output:
OnMessageReceived:
Token is missing from the request.
OnTokenValidated: {"alg":"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256","typ":"JWT"}.{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":"eaddca7f-0da3-4e5c-bc7d-8a3f79bf885d","http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":"Daan","nbf":1717685798,"exp":1720277798}
Normally, logging helps me to solve an issue but this is just makes stuff confusing?
Why isn’t my controller method called?
Why is my token “validated” but also “missing”?
How can I make sure my controller method is called?