10

Using using Microsoft.AspNetCore.Authentication.JwtBearer; I have been unable to figure out how to change the "Bearer " key in the header to something else, in this case I'd like it to be "Token ".

Startup.cs

services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
             {
                 x.RequireHttpsMetadata = false;
                 x.SaveToken = true;
                 x.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateIssuerSigningKey = true,
                     IssuerSigningKey = new SymmetricSecurityKey(key),
                     ValidateIssuer = false,
                     ValidateAudience = false,
                     ValidateLifetime = true,
                     ValidIssuer = Configuration.GetValue<string>("JwtIssuer"),
                     ValidAudience = Configuration.GetValue<string>("JwtAudience"),
                 };
                 x.Events = new JwtBearerEvents
                 {
                     OnAuthenticationFailed = context =>
                     {
                         if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         {
                             context.Response.Headers.Add("Token-Expired", "true");
                         }
                         return Task.CompletedTask;
                     }
                 };
             });

When I do something like

GET {{protocol}}://{{url}}/users HTTP/1.1
Authorization: Bearer {{token}}

The token works, but I could not figure out how to customize it to be something like.

GET {{protocol}}://{{url}}/users HTTP/1.1
Authorization: Token {{token}}


lastlink
  • 1,505
  • 2
  • 19
  • 29

3 Answers3

25

The implementation of the JwtBearer authentication handler lives inside of JwtBearerHandler, where the Authorization header is read and split using the format Bearer .... Here's what that looks like:

string authorization = Request.Headers["Authorization"];

// If no authorization header found, nothing to process further
if (string.IsNullOrEmpty(authorization))
{
    return AuthenticateResult.NoResult();
}

if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
{
    token = authorization.Substring("Bearer ".Length).Trim();
}

// If no token found, no further work possible
if (string.IsNullOrEmpty(token))
{
    return AuthenticateResult.NoResult();
}

As the code above shows, this is hardcoded to use Bearer. However, JwtBearerEvents includes an OnMessageReceived property that allows you to hook into the process for retrieving the JWT from the incoming request. If you provide an implementation for this event, you can use your own processing to extract the JWT however you'd like.

Taking the implementation from above with a few changes, that event handler implementation would like something like this:

x.Events = new JwtBearerEvents
{
    // ...
    OnMessageReceived = context =>
    {
        string authorization = context.Request.Headers["Authorization"];

        // If no authorization header found, nothing to process further
        if (string.IsNullOrEmpty(authorization))
        {
            context.NoResult();
            return Task.CompletedTask;
        }

        if (authorization.StartsWith("Token ", StringComparison.OrdinalIgnoreCase))
        {
            context.Token = authorization.Substring("Token ".Length).Trim();
        }

        // If no token found, no further work possible
        if (string.IsNullOrEmpty(context.Token))
        {
            context.NoResult();
            return Task.CompletedTask;
        }

        return Task.CompletedTask;
    }
};
Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
0

Prefix Bearer ... comes from JwtBearerDefaults.AuthenticationScheme you set as a default auth scheme.

If you'd like, you could use custom authentication like this or similar:

// Add authentication
services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CustomAuthOptions.DefaultScheme;
    options.DefaultChallengeScheme = CustomAuthOptions.DefaultScheme;
})
// Call custom authentication extension method
.AddCustomAuth(options =>
    {
    // Configure password for authentication
    options.AuthKey = "custom auth key";
});

.. or maybe even combine the custom scheme name with .AddJwtBearer(x => ...) - never tried this. Or maybe you are just looking for something like protecting your API with API Keys.

Dmitry Pavlov
  • 30,789
  • 8
  • 97
  • 121
  • I'm not trying to do hardcoded api keys, but change the bearer keyword in the header e.g. `authorization: header xxx` to `authorization: token xxx` – lastlink Jul 02 '19 at 19:50
  • I got it. See "Prefix Bearer ... comes from JwtBearerDefaults.AuthenticationScheme" which is just "Bearer" string constant. I suspect this constant value is used inside auth middleware, but you maybe could just try to set "Token" string as scheme name and then use the same `.AddJwtBearer(x => ...)` config. – Dmitry Pavlov Jul 02 '19 at 20:07
  • I tried setting token as the scheme name in various combinations and it didn’t work – lastlink Jul 02 '19 at 23:20
  • I see. So it seems you either need to agree using Bearer, or implement your own bearer-like auth [custom authentication](https://ignas.me/tech/custom-authentication-asp-net-core-20/) which will use `Token` prefix as you want. – Dmitry Pavlov Jul 03 '19 at 19:30
0

This implementation was quite simple to implement for me: link

services.AddAuthentication().AddJwtBearer(options => {
           options.Events = new JwtBearerEvents {
                            OnMessageReceived = ctx => {
                                if (ctx.Request.Headers.ContainsKey("SpecialApiKey"))
                                {
                                    var bearerToken = ctx.Request.Headers["SpecialApiKey"].ElementAt(0);
                                    var token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
                                    ctx.Token = token;
                                }
                                return Task.CompletedTask;
                            }
                        };
                    });
Umar Kayondo
  • 405
  • 4
  • 9