authenticationauthorizationasp.net-core-webapibearer-tokencookie-httponly

.NET - Is there a way to validate the httponly token and header token?


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?


Solution

  • 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();
    

    enter image description here

    Server authenticated and token validated , endpoint hit.