Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using dependency injection to replace JWT Bearer Options in ASP.NET Core

In the web API, I'm securing with Jwt Auth, I have the following ConfigureServices Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection")));
    // Some additional application dependencies here with AddTransient()...
    services.AddMvc();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
           options.Authority = "xxxxx";
           options.RequireHttpsMetadata = false;
           options.Audience = "xxxxx";
           options.BackchannelHttpHandler = BackChannelHandler;
        });
}

Here, BackChannelHandler is a public property of the Startup.cs:

public static HttpMessageHandler BackChannelHandler { get; set; }

The reason why I'm using this property is that when I'm doing integration testing using xUnit, I'm using in-memory TestServer from Microsoft.AspNetCore.TestHost. So, I need to register backchannel handler in TestFixture class like

testIdentityServer = new TestServer(identityServerBuilder);
My.Project.Startup.BackChannelHandler = testIdentityServer.CreateHandler();
testApiServer = new TestServer(apiServerBuilder);

While this is working fine, I would like to override either the services.AddAuthentication() or AddJwtBearer() in the DI container, so I can inject the authentication middleware configuration for testing purposes instead of using a public static property just like how I would do with any other dependency. When I try to do this using:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
       options.Authority = "xxxxx";
       options.RequireHttpsMetadata = false;
       options.Audience = "xxxxx";
       options.BackchannelHttpHandler = testIdentityServer.CreateHandler();
    });

in TestFixture.cs I get the error: authentication scheme with "Bearer token" already exists.

How can I do this with correctly ASP.NET Core?

like image 231
bravo2zero Avatar asked Jul 30 '18 03:07

bravo2zero


People also ask

What is the use of dependency injection in .NET Core?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.

What is IServiceCollection in .NET Core?

} IServiceCollection is the collection of the service descriptors. We can register our services in this collection with different lifestyles (Transient, scoped, singleton) IServiceProvider is the simple built-in container that is included in ASP.NET Core that supports constructor injection by default.

What is Authenticationschemes?

AuthenticationScheme is the name of the scheme to use by default when a specific scheme isn't requested. If multiple schemes are used, authorization policies (or authorization attributes) can specify the authentication scheme (or schemes) they depend on to authenticate the user.


1 Answers

The behaviour you encounter is normal as you can't have 2 handlers for the same authentication scheme. Here, AddJwtBearer adds a handler for the authentication scheme Bearer, which value comes from JwtBearerDefaults.AuthenticationScheme.

The lambda expression you pass to the AddJwtBearer is registered as a named option configuration, the name it's registered against being the authentication scheme.

So here's what you could do in your test project:

services.PostConfigure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.BackchannelHttpHandler = testIdentityServer.CreateHandler();
});

Doing this will not change the authentication schemes that are already registered in the container but will only modify the options associated with the JWT handler.

like image 152
Mickaël Derriey Avatar answered Oct 13 '22 18:10

Mickaël Derriey