Authenticating tokens from multiple sources (e.g Cognito and Azure)

Viewed 1347

We're working on an API that allows users authenticating through a number of different providers. The individual providers are not an issue, but using them together is proving to be a challenge.

It seems that adding more than 1 provider throws a InvalidOperationException with "Scheme already exists: Bearer" when the application starts up.

Below is the ConfigureServices function from Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "Value";
            options.Audience = "Value";
        })
        .AddMicrosoftIdentityWebApi(options =>
        {
            Configuration.Bind("AzureAdB2C", options);

            options.TokenValidationParameters.NameClaimType = "name";
        },
        options => { Configuration.Bind("AzureAdB2C", options); });
    
    services.AddControllers();
    services.AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder(
            JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .Build();
    });
}

I'm using the Microsoft example for authenticating with Azure AD as a starting point. Removing either the AddJwtBearer or AddMicrosoftIdentityWebApi calls works fine, but I need to configure both providers for our use-case.

Is there a way to do this with .NET Core 3.1 or up?

1 Answers

We can't register 2 authentications under same scheme name. So we need to register the 2 authentication schemes with different name(or one with default and another with a scheme name) In my case I am registering 2 authentication schemes:

  1. My own JWT scheme with our app name "MyAppName",
  2. Azure AD authentication with JWT default scheme JwtBearerDefaults.AuthenticationScheme, as I was not able to add it with custom scheme name.

I was able to make it work with the following configuration:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer("MyAppName",options =>
    {
         options.Authority = "Value";
         options.Audience = "Value";                    
    })
    .AddMicrosoftIdentityWebApi(Configuration, "AzureAd");

and Authorization configuration:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder(
        "MyAppName",
        JwtBearerDefaults.AuthenticationScheme)
    .RequireAuthenticatedUser()
    .Build();
});
Related