AspNetCore.Docs icon indicating copy to clipboard operation
AspNetCore.Docs copied to clipboard

AddJwtBearer(scheme) cannot be overriden due to hard coded implementation with "Bearer"

Open codepic opened this issue 1 year ago • 3 comments

Description

The documentation says "Bearer" is the typical default scheme in JWT-bearer based enabled apps, but the default scheme can be overridden by setting the DefaultScheme property as in the preceding example. and gives us an example:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication()
  .AddJwtBearer()
  .AddJwtBearer("LocalAuthIssuer");
  
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

However, the JwtBearerHandler is hard coded to Bearer scheme, rendering the .AddJwtBearer(scheme) extension method pretty much useless: https://github.com/dotnet/aspnetcore/blob/258f8baa683db26ea46a00618a8b9b4d8db764b4/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs#L84

Page URL

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/security?view=aspnetcore-8.0&source=docs

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/fundamentals/minimal-apis/security.md

Document ID

3a9d7eb8-6c1f-4619-00fa-9b69dbe3dcea

Article author

@captainsafia

codepic avatar Aug 29 '24 06:08 codepic

@codepic thanks for reporting this. We're heads down for the .NET 9 release and this might not get looked at until after GA. I've recorded this in our calendar but if you don't hear back after GA let me know.

Rick-Anderson avatar Aug 29 '24 18:08 Rick-Anderson

The scheme has a double meaning (AFAIK), and possibly created the confusion which lead to issue.

Within the context of the docs, the scheme is used to name a JWT Bearer scheme's configuration, not to configure one of "broader" strategy authentication schemes (basic authentication, bearer authentication, digest authentication, ...).

Using different bearer schemes can be useful if your application accepts tokens from different issuers. This is explained in the docs:

image

The default scheme within the documentation refers to the default JwtBearer scheme name (JwtBearerDefaults.AuthenticationScheme, which is Bearer), the code for this can be found at

https://github.com/dotnet/aspnetcore/blob/3d7234c36aaf15c6442ffc0dc058dea0585d6586/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs#L24-L25

To create a custom authentication scheme implementation I think the best solution is to create your own AuthenticationHandler.

timdeschryver avatar Oct 01 '24 18:10 timdeschryver

@timdeschryver like said, the "Bearer " is hard coded in the JwtBearerHandler and only in that case the token gets assigned a value.

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

source

If the documentation communicates the possibility of using a custom scheme, then it should also make the reader aware that the token will not get assigned a value by the JwtBearerHandler.

If this hard coding is an intended functionality, the documentation should make the reader aware that in order to capture the token, they need to capture it in the JwtBearerEvents.OnMessageReceived (as suggested in the source code).

options.Events = new JwtBearerEvents()
{
    OnMessageReceived = context =>
    {
        var authorization = Request.Headers.Authorization.ToString();
        context.Token = authorization?.Substring("LocalAuthIssuer ".Length).Trim();
        return Task.CompletedTask;
    }
}

or, as you suggested, implement their own AuthenticationHandler.

Current documentation isn't clear about it and it leads to unnecessary debugging and source-code browsing.

In my opinion, if .AddJwtBearer() allows for using a custom scheme, then JwtBearerHandler should respect the custom scheme and capture the token instead of being hard coded to Bearer. But this is a change that would most probably lead to a lot of regression issues so I digress.

codepic avatar Oct 03 '24 17:10 codepic