Read JWT token from different HTTP header in ASP.NET Core

10.9k Views Asked by At

In an ASP.NET Core API project, I need to validate another JWT Bearer token located in header different than the Authorization header. For example, imagine sending a GET request to get products to /api/products with a Bearer token in a header named AccessToken.

curl --location --request GET 'https://localhost/api/products' \
--header 'AccessToken: <bearer_token>'

I'm referencing the Microsoft.AspNetCore.Authentication.JwtBearer package and setting authentication in the API project like this:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => Configuration.Bind("JwtSettings", options));

However, I cannot find anything regarding a header name inside the JwtBearerOptions Class.

How can I configure the JWT authentication to read the JWT from a header named "AccessToken"? Is it even possible using the Microsoft.AspNetCore.Authentication.JwtBearer package?

1

There are 1 best solutions below

5
On BEST ANSWER

The solutions seems to be to use the JwtBearerEvents class. In it, there's a delegate property named OnMessageReceived that it's "invoked when a protocol message is first received". The delegate will pass a object of type of MessageReceivedContext, where it has a property named Token that according to the documentation "This will give the application an opportunity to retrieve a token from an alternative location".

Create a class that inherits from JwtBearerEvents and in the OnMessageReceived event set the token in the context object to the value from the header "AccessToken".

/// <summary>
/// Singleton class handler of events related to JWT authentication
/// </summary>
public class AuthEventsHandler : JwtBearerEvents
{
    private const string BearerPrefix = "Bearer ";

    private AuthEventsHandler() => OnMessageReceived = MessageReceivedHandler;

    /// <summary>
    /// Gets single available instance of <see cref="AuthEventsHandler"/>
    /// </summary>
    public static AuthEventsHandler Instance { get; } = new AuthEventsHandler();

    private Task MessageReceivedHandler(MessageReceivedContext context)
    {
        if (context.Request.Headers.TryGetValue("AccessToken", out StringValues headerValue))
        {
            string token = headerValue;
            if (!string.IsNullOrEmpty(token) && token.StartsWith(BearerPrefix))
            {
                token = token.Substring(BearerPrefix.Length);
            }

            context.Token = token;
        }

        return Task.CompletedTask;
    }
}

Finally, add the events class to the JWT authentication at the Startup class.

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => 
{
    Configuration.Bind("JwtSettings", options);
    options.Events = AuthEventsHandler.Instance;
});