Edit of December 2019: please consider this answer before anything else:
Use multiple JWT Bearer Authentication
My old answer (that does not fit using multiple JWT but only JWT + API key, as a user commented):
Another possibility is to determine at runtime which authentication policy scheme to choose, I had the case where I could have an http authentication bearer token header or a cookie.
So, thanks to https://github.com/aspnet/Security/issues/1469
JWT token if any in request header, then OpenIdConnect (Azure AD) or anything else.
public void ConfigureServices(IServiceCollection services)
{
// Add CORS
services.AddCors();
// Add authentication before adding MVC
// Add JWT and Azure AD (that uses OpenIdConnect) and cookies.
// Use a smart policy scheme to choose the correct authentication scheme at runtime
services
.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = "smart";
sharedOptions.DefaultChallengeScheme = "smart";
})
.AddPolicyScheme("smart", "Authorization Bearer or OIDC", options =>
{
options.ForwardDefaultSelector = context =>
{
var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
if (authHeader?.StartsWith("Bearer ") == true)
{
return JwtBearerDefaults.AuthenticationScheme;
}
return OpenIdConnectDefaults.AuthenticationScheme;
};
})
.AddJwtBearer(o =>
{
o.Authority = Configuration["JWT:Authentication:Authority"];
o.Audience = Configuration["JWT:Authentication:ClientId"];
o.SaveToken = true;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddAzureAd(options => Configuration.Bind("AzureAd", options));
services
.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
// Authentication is required by default
config.Filters.Add(new AuthorizeFilter(policy));
config.RespectBrowserAcceptHeader = true;
});
...
}
Edit of 07/2019: I must add a link to the following proposal, because it’s very helpful too: you may not use parameters in AddAuthentication()
as I did, because this would setup a default scheme. Everything is well explained here:
Use multiple JWT Bearer Authentication.
I really like this other approach!