.netasp.net-coreauthenticationauthorization.net-7.0

Add custom JwtBearerHandler to "AddMicrosoftIdentityWebApi" in .net7


How does one wire a custom JwtBearerHandler in .NET7 to this:

 builder.Services.AddAuthentication() .AddMicrosoftIdentityWebApi(builder.Configuration);

Alternatively, how would I translate the previous statement into this

builder.Services
.AddAuthentication()
.AddScheme<JwtBearerOptions, CustomJwtHandler>("AzureAd", options => Configuration.Bind("AzureAd", options))

like they do in this example in the answer : https://stackoverflow.com/a/68258618/441365


Solution

  • You could directly replace built-in JwtBearerHandler by CustomJwtBearerHandler using DI.

    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
    builder.Services.AddTransient<JwtBearerHandler, CustomJwtBearerHandler>();
    

    You could test logic like following which will work in the "MicrosoftIdentityWebApi" pipleline.

        public class CustomJwtBearerHandler : JwtBearerHandler
        {
            public CustomJwtBearerHandler(
                IOptionsMonitor<JwtBearerOptions> options,
                ILoggerFactory logger,
                System.Text.Encodings.Web.UrlEncoder encoder,
                ISystemClock clock)
                : base(options, logger, encoder, clock)
            {
            }
    
            protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
            {
                // Perform your custom authentication logic here
                var result = await base.HandleAuthenticateAsync();
    
                if (result.Succeeded)
                {
                    // Custom logic, e.g., logging or additional validation
                    var ticket = result.Ticket;
    
                    // Example: Reject if a custom claim is missing
                    if (!ticket.Principal.HasClaim(c => c.Type == "custom-claim"))
                    {
                        return AuthenticateResult.Fail("Missing required custom claim.");
                    }
                }
    
                return result;
            }
        }