简体   繁体   中英

Multiple Azure AD B2C login screens in progressive ASP web app

I am currently looking to design and implement Azure AD B2C for a client who wants a specific login workflow that is split into two user types:

  • Customers - Using Azure AD B2C user flow utilising email and phone signup. Utilises the standard internal identity provider

  • Internal users and suppliers - Using multiple Active Directory tenants, one for the client internal users and a different one for all the suppliers accounts. I have created OpenIDConnect identity providers for both.

I have the user flows for both user logins designed in Azure AD B2C and want to surface them within an MVC or Blazor web app. The client has specified that there needs to be separate login pages as they don't want customers seeing the AD identity buttons.

Thinking that this would be a simple case of adding a new B2C identity authentication scheme I added a new configuration section to the appsettings.json and the below additional line to the Startup.cs .

    services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
        .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C_UsernamePassword", options));

    services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
        .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C_ActiveDirectory", options));

On running the code it appears that this scenario is not supported as I get the below exception:

System.InvalidOperationException: 'Scheme already exists: AzureADB2C'

My question is how do I support this Azure AD B2C multiple page login scenario within a single ASP web app? I want to avoid multiple web apps as this would result in a large duplication of code and cost.

Ok, I figured this out with some help from a few articles. It isn't possible to add multiple AzureADB2C authentication providers using .AddAzureADB2C extension method so I added the other as an OpenIdConnect provider using the .AddOpenIdConnect extendion method as below:

    services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
        .AddAzureADB2C(options => {
            this.Configuration.Bind("IdentityProvider1", options);
        })
        .AddOpenIdConnect("AD", options =>
        {
            AzureADB2COptions b2cActiveDirectoryOptions = new AzureADB2COptions();
            this.Configuration.Bind("<IdentityProvider2>", b2cActiveDirectoryOptions);
            var tenantName = b2cActiveDirectoryOptions.Domain.Substring(0, b2cActiveDirectoryOptions.Domain.IndexOf('.'));
            options.Authority = $"https://{tenantName}.b2clogin.com/tfp/{b2cActiveDirectoryOptions.Domain}/{b2cActiveDirectoryOptions.SignUpSignInPolicyId}/v2.0";
            options.ClientId = b2cActiveDirectoryOptions.ClientId;
            options.CallbackPath = b2cActiveDirectoryOptions.CallbackPath + "-AD";
            options.TokenValidationParameters.NameClaimType = "name";
        });

With the appsetting.json look as below:

{
  "IdentityProvider1": {
    "Instance": "https://<mytenant>.b2clogin.com/tfp/",
    "ClientId": "<myClientId>",
    "CallbackPath": "/signin-oidc",
    "Domain": "<mytenant>.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_SignUpAndSignIn",
    "ResetPasswordPolicyId": "B2C_1_ResetPassword",
    "EditProfilePolicyId": "",
    "ClientSecret": "<mySecret>"
  },
  "IdentityProvider2": {
    "Instance": "https://<mytenant>.b2clogin.com/tfp/",
    "ClientId": "<myClientId>",
    "CallbackPath": "/signin-oidc",
    "Domain": "<mytenant>.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_Auth",
    "ResetPasswordPolicyId": "B2C_1_ResetPassword",
    "EditProfilePolicyId": "",
    "ClientSecret": "<mySecret>"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

As I am now using Implicit grants for both the B2C and OpenIdConnect authentication providers I had to enable Access tokens (used for implicit flows) and ID tokens (used for implicit and hybrid flows) within the App Registrations Authentication blade.

Splitting out the User Workflows so that IdentityProvider1 using Local Accounts and IdentityProvider2 used Azure AD via OpenID Connect gave me the result I needed.

To test this I changed the Index.cshtlp page to include a couple of links as below:

<div class="text-center">
    <a class="nav-link text-dark" href="/AzureADB2C/Account/SignIn">Customer Sign In</a>
</div>

<div class="text-center">
    <a class="nav-link text-dark" href="/AzureADB2C/Account/SignIn/AD">Active Directory User Sign In</a>
</div>

The local account signup and signin was available via ~//AzureADB2C/Account/SignIn with the Azure AD signin and signup available via ~/AzureADB2C/Account/SignIn/AD

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM