I have an ASP.NET Core 8.0 Web API that is configured to authenticate with http-only JWT token.
This is my code to create the authentication and authorization:
builder.Services.AddAuthorizationBuilder()
.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser().Build());
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddCookie(opt =>
{
opt.Cookie.Name = Token.TokenKey;
})
.AddJwtBearer(opt =>
{
opt.RequireHttpsMetadata = false;
opt.SaveToken = true;
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("myKey")),
ValidateIssuer = false,
ValidateAudience = false
};
opt.Events = new JwtBearerEvents
{
OnMessageReceived = ctx =>
{
ctx.Token = ctx.Request.Cookies[Token.TokenKey];
return Task.CompletedTask;
}
};
});
My scenario: I want to work with two tokens. One sent by the header and one managed by the server using http-only cookies. My goal with this approach is increase the security of my API, so that requests only become valid if both tokens are valid.
My problem: currently the API only returns the 401 Unauthorized
error if I am not authenticated using the http-only cookie, but if I am authenticated on the server side (with the http-only cookie), the request reaches the API, even without sending the header token.
My question: I want the API to only be reached if the user is authenticated by the server with the http-only cookie and another valid token is sent through the header. Is there any way to do this?
You could use custom middleware to implement header token validation. The logic is to add one more token auth after server authenticated.
1.Define your middleware
public class ValidateHeaderTokenMiddleware
{
private readonly RequestDelegate _next;
public ValidateHeaderTokenMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.User.Identity.IsAuthenticated)
{
var headerToken = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
// Custom vaidation logic
if (!IsValidToken(headerToken))
{
context.Response.StatusCode = 401; // Unauthorized
await context.Response.WriteAsync("Invalid header token.");
return;
}
}
await _next(context);
}
private bool IsValidToken(string token)
{
// Custom vaidation logic
return true;
}
}
2.Register the service in program
app.UseAuthentication();
app.UseMiddleware<ValidateHeaderTokenMiddleware>();
app.UseAuthorization();
Server authenticated and token validated , endpoint hit.