Open Closed

Azure AD B2C implementation #7702


0
DireccionTI created

Hi, somebody has an example, recommendations, guides, etc. about how to implement Azure AD B2C in ASPNETZERO? Thanks a lot for your help!


2 Answer(s)
  • 0
    philhu created

    Hi, here is how I proceeded to implement Azure AD B2C OpenID :

    • In Azure AD, find your tenant name and tenant ID (= Directory ID)
    • In Azure AD B2C, find your signup/signin policy, and your application ID. Verify the application claims and make sure you check Email Address, Given Name, Surname
    • Enable OpenID in appsettings.json:
    "OpenId": {
          "IsEnabled": "true",
          "ClientId": "<applicationID>",
          "Authority": "https://<TenantName>.b2clogin.com/tfp/<TenantID>/b2c_1_signin/v2.0/",
          "LoginUrl": "https://<TenantName>.b2clogin.com/tfp/<TenantName>.onmicrosoft.com/<signupin_policy>/oauth2/v2.0/authorize",
          "ValidateIssuer": "false"
        },
    
    • Azure AD does not provide unique_name and email in the claims (it provide emails). To address this issue, I followed the technique explained in Question 5773 and implemented the class OpenIdConnectAuthProviderApi OpenIdConnectAuthProviderApi in YourProject.Web.Core\Authentication\External\OpenIdConnectAuthProviderApi .cs.

    • You have to change the lines that decode the claims (it was originally written for okta):

    var givenname = validatedToken.Claims.First(c => c.Type == "given_name").Value;
    var surname = validatedToken.Claims.First(c => c.Type == "family_name").Value; 
    var emails = validatedToken.Claims.First(c => c.Type == "emails").Value;
    var email = string.Empty;
    if (!string.IsNullOrEmpty(emails)) email = emails.Split(' ').First();
    
    return new ExternalAuthUserInfo
    {
         Provider = Name,
         ProviderKey = validatedToken.Subject,
         Name = givenname,
         Surname = surname,
         EmailAddress = email
      };
    
    
    • Now edit GetExternalUserInfo in YourProject.Web.Core\Controllers\TokenAuthController.cs to use the proper version of GetUserInfo:
    private async Task<ExternalAuthUserInfo> GetExternalUserInfo(ExternalAuthenticateModel model)
     {
         ExternalAuthUserInfo userInfo = null;
         if (model.AuthProvider == OpenIdConnectAuthProviderApi.Name)
             userInfo = await _openIdConnectAuthProviderApi.GetUserInfo(model.AuthProvider, model.ProviderAccessCode);
         else
             userInfo = await _externalAuthManager.GetUserInfo(model.AuthProvider, model.ProviderAccessCode);
    
          if (userInfo.ProviderKey != model.ProviderKey)
          {
               throw new UserFriendlyException(L("CouldNotValidateExternalUser"));
           }
    
         return userInfo;
    }
    

    (do not forget to instantiate _openIdConnectAuthProviderApi; see how _externalAuthManager is instantiated)

    • I found useful to add
                if (bool.Parse(configuration["Authentication:OpenId:IsEnabled"]))
                {
                    IdentityModelEventSource.ShowPII = true;
                }
    

    in AcmePhoneBookDemo.Web.Startup::AuthConfigurer::Configure. It enables revealing the PII exception messages.

  • 0
    ismcagdas created

    Hi @philhu

    Instead of creating a custom implementation of OpenIdConnectAuthProviderApi, you can use ClaimsMappings section of OpenId configuration in appsettings.json. It allows you to map email claim to unique_name.