title: .NET Core route based authentication with multiple B2C environments
body: <h1>Situation</h1>
  <p>We have clients that should be able to login into our application. Our clients do also have clients, who also may login. Therefore we have an Azure AD B2C environment per client.</p>
  <p>So, we want to have one single application that can be used to authenticate against multiple Azure B2C environments. We want to have this route-based. So:</p>
  <p>/client1 goes to B2C environment Client1B2C, with user flow B2C_1_Client1</p>
  <p>/client2 goes to B2C environment Client2B2C, with user flow B2C_1_Client2</p>
  <h1>Challenge</h1>
  <p>So, we need to define multiple instances of AddOpenIdConnect. I do this inside a specific builder, so my Startup.cs keeps clean:</p>
  <p><strong>Startup.cs</strong></p>
  <pre><code>            ...
              var AzureAdB2CSettings = new List&lt;AzureAdB2COptions&gt;();
              Configuration.GetSection(&quot;Authentication:AzureAdB2C&quot;).Bind(AzureAdB2CSettings, c =&gt; c.BindNonPublicProperties = true);
  
              services.AddAuthentication(sharedOptions =&gt;
              {
                  ...
              })
              .AddAzureAdB2C(options =&gt; Configuration.Bind(&quot;Authentication:AzureAdB2C&quot;, options), AzureAdB2CSettings)
              ...
  </code></pre>
  <p>And there is the builder:</p>
  <p><strong>AzureAdB2CAuthenticationBuilderExtensions.cs</strong></p>
  <pre><code>        ...
          public static string policyToUse;
          
          public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action&lt;AzureAdB2COptions&gt; configureOptions, List&lt;AzureAdB2COptions&gt; openIdOptions)
          {
              ...
              foreach(var b2c in openIdOptions)
              {
                  builder.AddOpenIdConnect(b2c.SignUpSignInPolicyId, b2c.SignUpSignInPolicyId, options =&gt;
                  {
                      options.Authority = b2c.Authority;
                      options.ClientId = b2c.ClientId;
                      options.CallbackPath = b2c.CallbackPath;
                      options.SignedOutCallbackPath = b2c.SignedOutCallbackPath;
                      options.ClientSecret = b2c.ClientSecret;
                  });
              }
  
              return builder;
          }
          ...
  
          public Task OnRedirectToIdentityProvider(RedirectContext context)
          {
              ...
              string policyToUse = &quot;B2C_1_&quot; + context.Request.Query[&quot;area&quot;];
              ...
  
              var b2cSettings = AzureAdB2CSettings.Find(x =&gt; x.SignUpSignInPolicyId.ToLower().Equals(policyToUse.ToLower()));
  
              AzureAdB2CAuthenticationBuilderExtensions.policyToUse = b2cSettings.DefaultPolicy;
              ...
  
  </code></pre>
  <p>Yippee ya yeeey! We can have a dynamic amount of add AddOpenIdConnect, based on a configuration file. The chosen authentication scheme has been set to the static string &quot;AzureAdB2CAuthenticationBuilderExtension.policyToUse&quot;.</p>
  <p>But now it comes... how to define the Authorization header?</p>
  <p><strong>BackofficeController.cs</strong></p>
  <pre><code>        ...
          [Authorize(AuthenticationSchemes = AzureAdB2CAuthenticationBuilderExtensions.policyToUse)]
          public async Task&lt;IActionResult&gt; ChooseBackoffice()
          {
              ...
          }
          ...
  </code></pre>
  <p>AUTCH!! You can't use dynamic attributes... Have tried to set the chosen scheme as a default, but it seems we can only define a default at startup, not during runtime...</p>
  <p>Any suggestions how to solve this challenge?</p>