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?
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.
} 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With