Multiple authentication schemes do not work on Azure (app fails to start)

Jörg Auberg 20 Reputation points
2023-01-20T12:55:41.74+00:00

I try to work with two app registrations that uses one app service.

appsettings.json

"AzureAdInternal": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "demo.example.com",
    "TenantId": "tenantId",
    "ClientId": "clientId",
    "ClientSecret": "clientSecret",
    "CallbackPath": "/signin-oidc"
  },
  "AzureAdExternal": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "demo.example.com",
    "TenantId": "tenantId",
    "ClientId": "clientId",
    "ClientSecret": "clientSecret",
    "CallbackPath": "/signin-oidc"
	}

Program.cs

// Multiple authentication (internal/external)
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection(Configuration.AzureActiveDirectoryInternalIdentifier), 
    OpenIdConnectDefaults.AuthenticationScheme)
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
            .AddMicrosoftGraph(builder.Configuration.GetSection(Configuration.MicrosoftGraphIdentifier))
            .AddInMemoryTokenCaches();

builder.Services.AddAuthentication()
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection(Configuration.AzureActiveDirectoryExternalIdentifier),
    "AzureAD", "cookiesAzureAD")
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
            .AddMicrosoftGraph(builder.Configuration.GetSection(Configuration.MicrosoftGraphIdentifier))
            .AddInMemoryTokenCaches();

Locally, it works, but during the publishing process in VS2022 the app fails to start.

Unhandled exception. System.InvalidOperationException: Scheme already exists: AppServicesAuthentication
   at Microsoft.AspNetCore.Authentication.AuthenticationOptions.AddScheme(String name, Action`1 configureBuilder)
   at Microsoft.AspNetCore.Authentication.AuthenticationBuilder.<>c__DisplayClass4_0`2.<AddSchemeHelper>b__0(AuthenticationOptions o)
   at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value()
   at Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options, IDictionary`2 schemes)
   at Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider..ctor(IOptions`1 options)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Builder.WebApplication.get_ServerFeatures()
   at Microsoft.AspNetCore.Builder.WebApplication..ctor(IHost host)
   at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()

How can I solve this problem?

Many thanks for an answer.

Azure App Services
Azure App Services
A feature of Azure App Service used to create and deploy scalable, mission-critical web apps.
4,326 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
2,585 questions
No comments
{count} votes

1 answer

Sort by: Most helpful
  1. JasonPan - MSFT 1,146 Reputation points Microsoft Employee
    2023-01-25T07:01:23.0233333+00:00

    Hi @Jörg Auberg,

    It seems that you have a misunderstanding about the multi-tenant app.

    When we create an app in App Registrations, we are already asked to choose whether the type of app is single-tenant or multi-tenant.

    So in the appsetting.json code, we only need to configure the configuration of an AzureAd. TenantId needs to be modified to common.

    Up to now, not all users of the organization can log in, and the administrator of the other tenant needs to authorize it, please refer to the following document.

    Grant tenant-wide admin consent to an application


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Jason