Reputation: 139
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?
Upvotes: 9
Views: 4961
Reputation: 13704
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.
Upvotes: 14