1

We have implemented Sitecore Federated Authentication with Azure AD (similar to http://sitecore.badalkotecha.com/2017/11/federated-authentication-for-sitecore-9-integrating-with-azuread.html). Now we have a requirement to add two more sites (multisite) with same tenant id. In short 3 webSites, 1 TenantId and 3 ClientIds. we have extended the owin.identityProviders -> processor and redirecting the user to microsoft login along with ClientId and RedirectUrl. But the processor is always pointing to one ClientID. Please suggest how to achieve Sitecore Federated Authentication with Azure AD for Multisite.

AzureAD Config

  <setting name="Site2_ClientId" value="yyyyyyy" />
  <setting name="Site2_SecretKey" value="yyyyyyy" />
  <setting name="Site2_RedirectURL" value="https://Site2.domainName.com" />

  <setting name="Site3_ClientId" value="zzzzzzz" />
  <setting name="Site3_SecretKey" value="zzzzzzzz" />
  <setting name="Site3_RedirectURL" value="https://Site3.domainName.com" />
  
</settings>
<pipelines>
  <owin.identityProviders>
    <processor type="xxxxxxx.Foundation.ScExtensions.Pipeline.AzureADFedAuthProcessor, xxxxxxx.Foundation.ScExtensions" resolve="true">
      
    </processor>
    
  </owin.identityProviders>
</pipelines>
<federatedAuthentication>
  <identityProviders hint="list:AddIdentityProvider">
    <identityProvider id="xxxxxxx.sc.azureAD" type="Sitecore.Owin.Authentication.Configuration.DefaultIdentityProvider, Sitecore.Owin.Authentication">
      <param desc="name">$(id)</param>
      <param desc="domainManager" type="Sitecore.Abstractions.BaseDomainManager" resolve="true" />
      <caption>SignIn</caption>
      <domain>extranet</domain>
      <enabled>true</enabled>
      <icon>/sitecore/shell/themes/standard/Images/24x24/msazure.png</icon>
      <transformations hint="list:AddTransformation">
       <!--
       Transformations
       -->
      </transformations>
    </identityProvider>
  </identityProviders>
  <!-- Property initializer assigns claim values to sitecore user properties -->
  <propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication">
    <maps hint="list">
     <!--
     CLAIMS MAPPING
     -->
    </maps>
  </propertyInitializer>
  <identityProvidersPerSites>
    <mapEntry name="all" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication" resolve="true">
      <sites hint="list">
        <site>WebSite1</site>
        <site>WebSite2</site>
        <site>WebSite3</site>
      </sites>
      <!-- Registered identity providers for above providers -->
      <identityProviders hint="list:AddIdentityProvider">
        <identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='xxxxxxx.sc.azureAD']" />
      </identityProviders>
      <!-- ExternalUserBuilder is what creates a user with customusername in Sitecore and assigns roles based on claim transformation configured above -->
      <externalUserBuilder type="Sitecore.Owin.Authentication.Services.DefaultExternalUserBuilder, Sitecore.Owin.Authentication" resolve="true">
        <param desc="isPersistentUser">false</param>
      </externalUserBuilder>
    </mapEntry>
    <mapEntry name="sites with the web database" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication" resolve="true">
      <sites hint="list">
        <site>database:web</site>
      </sites>
      <identityProviders hint="list:AddIdentityProvider">
        <identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='xxxxxxx.sc.azureAD']" />
      </identityProviders>
    </mapEntry>
    <mapEntry name="all sites" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication" resolve="true">          
      <sites hint="list">
        <site>regexp:.*</site>
      </sites>
      <identityProviders hint="list:AddIdentityProvider">
        <identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='xxxxxxx.sc.azureAD']" />
      </identityProviders>
      <externalUserBuilder type="Sitecore.Owin.Authentication.Services.DefaultExternalUserBuilder, Sitecore.Owin.Authentication" resolve="true">
        <IsPersistentUser>true</IsPersistentUser>
      </externalUserBuilder>
    </mapEntry>
  </identityProvidersPerSites>
</federatedAuthentication>
<sites>
  <site name="WebSite1" requireLogin="true" loginPage="/api/sitecore/login/Site1SignIn"/>
  <site name="WebSite2" requireLogin="true" loginPage="/api/sitecore/login/Site2SignIn"/>
  <site name="WebSite3" requireLogin="true" loginPage="/api/sitecore/login/Site3SignIn"/>
  
</sites>

Processor Code

    public AzureADFedAuthProcessor(FederatedAuthenticationConfiguration federatedAuthenticationConfiguration, ICookieManager cookieManager, BaseSettings settings) : base(federatedAuthenticationConfiguration, cookieManager, settings)
    {
        federatedAuthenticationConfigurationLocal = federatedAuthenticationConfiguration;
    }

    protected override string IdentityProviderName => "xxxxxx.sc.azureAD";
    
    protected override void ProcessCore([NotNull] IdentityProvidersArgs args)
    {
        Assert.ArgumentNotNull(args, nameof(args));
        try
        {
            var identityProvider = this.GetIdentityProvider();
            var authenticationType = this.GetAuthenticationType();

            string tenant = Settings.GetSetting("Tenant");
            string postLogoutRedirectURI = Settings.GetSetting("PostLogoutRedirectURI");
            string aadInstance = Settings.GetSetting("AADInstance");
            string clientId, redirectURI;
            clientId = Settings.GetSetting("Site1_ClientId");
            redirectURI = Settings.GetSetting("Site1_RedirectURL");

            //WE NEED SOMETHING SIMILAR TO THIS
            //if (Session[Site] == webSite1)
            //{
            //    clientId = Settings.GetSetting("Site1_ClientId");
            //    redirectURI = Settings.GetSetting("Site1_RedirectURL");
            //}
            //else if (webSite2)
            //{
            //    clientId = Settings.GetSetting("Site2_ClientId");
            //    redirectURI = Settings.GetSetting("Site2_RedirectURL");
            //}
            //else
            //{
            //    clientId = Settings.GetSetting("Site3_ClientId");
            //    redirectURI = Settings.GetSetting("Site3_RedirectURL");
            //}

            string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
            args.App.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions()
            {
                CookieManager = new SystemWebCookieManager()
            });
            args.App.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Caption = identityProvider.Caption,
                AuthenticationType = authenticationType,
                AuthenticationMode = AuthenticationMode.Passive,
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectURI,
                RedirectUri = redirectURI,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = notification =>
                    {
                        var identity = notification.AuthenticationTicket.Identity;

                        foreach (var claimTransformationService in identityProvider.Transformations)
                        {
                            claimTransformationService.Transform(identity, new TransformationContext
                            (
                                federatedAuthenticationConfigurationLocal, identityProvider
                            ));
                        }

                        notification.AuthenticationTicket = new AuthenticationTicket(identity, notification.AuthenticationTicket.Properties);

                        return Task.CompletedTask;
                    }

                }
            });
        }
        catch(Exception ex)
        {
            Log.Error("AzureAD: Error in reaching out to AzureAD Authentication provider", ex, this);
        }
    }
}

Login Controller

public ActionResult SiteOneSignIn()
    {
        try
        {
            var url = "/";
            if (!string.IsNullOrEmpty(Request.QueryString?["returnUrl"]))
                url = Request.QueryString["returnUrl"];

            var corePipelineManager = DependencyResolver.Current.GetService<BaseCorePipelineManager>();
            var args = new GetSignInUrlInfoArgs("mysite", url);
            GetSignInUrlInfoPipeline.Run(corePipelineManager, args);

            return View("/Views/Login/Login.cshtml", args.Result);
        }
        catch (Exception ex)
        {
            Log.Error("Error in SignIn: ", ex, this);
            return null;
        }
    }

1 Answer 1

0

You need to duplicate the processor Id for each Site and from the controllers pass the unique IdentityProviderName as well.

protected override string IdentityProviderName => "xxxxxx.sc.azureAD";

Also, patch in the identityproviders for each site

<identityProviders hint="list:AddIdentityProvider">
    <identityProvider id="xxxxxxx.sc.azureAD"

Controller code for Integratign with AzureAdB2C : Assuming each Site to have its own LoginController

[Route("LoginForm/SignIn")]
        public void SignIn()
        {
            if (!Request.IsAuthenticated)
            {
                HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties() { RedirectUri = "/myaccount" },
                    new string[] { "UniqueIdentityProviderId", Startup.SignInPolicyId });
            }
        }
6
  • I'll add one more processor in <owin.identityProviders> <processor type="site1.AzureADProcessor"/> <processor type="site2.AzureADProcessor"/>. And one more Identity provider. But How can I map Site1 to Processor1 and Site2 to processor 2 ? where should i mention in the above config file ? Commented Jan 8, 2021 at 17:05
  • edited my answer
    – Abhay Dhar
    Commented Jan 8, 2021 at 18:53
  • Abhay, After adding one more provider and one more action method in login controller, both Site1 and Site 2 are going into endless loop. I mean from Site 1 to login.microsoft.com with Site1 client id and again login.microsoft.com to Site1 continuously. (similarly for Site2 and Site3). Commented Jan 10, 2021 at 11:19
  • Edit your question and add the new patch configuration file you've created for all 3 sites
    – Abhay Dhar
    Commented Jan 10, 2021 at 15:05
  • Abhay, made some changes in my Controller Action methods (Posted in Qzn). Added some script in View.cshtml. it started working. Thank you Abhay. Commented Jan 10, 2021 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.