How do you configure and inject JwtOptions in .net core 3.1 using TOptions?

Viewed 817

In .NetCore 3.0 and 3.1 they removed the ability to inject services into the Startup class unless you intentionally build a second service provider and duplicate your singleton services (gross). Almost all examples of configuring Jwt Bearer tokens for authentication show something like this:

.AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

This is great when you are working in a static environment, but I'm working in an environment where these settings are dynamic and are pulled from a web service that issues out configuration settings.

I found a really good walkthrough for using TOptions here:

https://andrewlock.net/avoiding-startup-service-injection-in-asp-net-core-3/

I'm trying to get this options pattern to work with JwtOptions.

I have added this to my ConfigureServices:

services.AddSingleton<IMyService, MyServiceImplementation>();
services.ConfigureOptions<ConfigureJwtBearerOptions>();
services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer();

This is my new options class:

public class ConfigureJwtBearerOptions : IConfigureNamedOptions<JwtBearerOptions>
{
    private IMyService myService;

    public ConfigureJwtBearerOptions(IMyService svc)
    {
        this.myService = svc;
    }

    public void Configure(string name, JwtBearerOptions options)
    {
        // Only configure the options if this is the correct instance
        if (name == JwtBearerDefaults.AuthenticationScheme)
        {
            //use your service to get your settings
            options.Authority = myService.GetAuthority();
            options.Audience = myService.GetAudience();
        }
    }

    // This won't be called, but is required for the IConfigureNamedOptions interface
    public void Configure(JwtBearerOptions options) => Configure(Options.DefaultName, options);
}

Is there a concept I'm missing? Do I need to remove .AddJwtBearer() all together since I am now injecting options?

Thanks!

1 Answers

I had multiple authentication schemes for IIS including Windows. The code above is working for me.

Related