1

We're using Sitecore.NET 9.1.0.

We're trying to trigger register, login and forgot password flows from Sitecore that will be used by end users of our website.

After a successful login we want to identify/create a Sitecore contact and update it's facets with the user details (for this we've create a custom processor added on owin.cookieAuthentication.signedIn pipeline)

I've configured federated authentication for Sitecore accounts but it seems I'm missing something, as the virtual user is not created at all in Sitecore after a successful login.

I've managed to trigger AD B2C flows from Sitecore using Owin challenges, the AspNet.Cookie is successfully created afte a register/login, however owin.cookieAuthentication.signedIn custom processor is not triggered.

My configurations are the following:

<pipelines>
  <owin.identityProviders>
    <processor type="Feature.ADB2C.Pipeline.Processors.IdentityProviderProcessor, Feature.ADB2C" resolve="true" />
  </owin.identityProviders>
  <owin.cookieAuthentication.signedIn>
    <processor type="Feature.Accounts.Pipelines.TrackSignedIn, Feature.Accounts" resolve="true" />
  </owin.cookieAuthentication.signedIn>
</pipelines>
<services>
  <register serviceType="Sitecore.Abstractions.BaseAuthenticationManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Security.AuthenticationManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
  <register serviceType="Sitecore.Abstractions.BaseTicketManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Security.TicketManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
  <register serviceType="Sitecore.Abstractions.BasePreviewManager, Sitecore.Kernel"
            implementationType="Sitecore.Owin.Authentication.Publishing.PreviewManager, Sitecore.Owin.Authentication"
            lifetime="Singleton" />
</services>
<federatedAuthentication type="Sitecore.Owin.Authentication.Configuration.FederatedAuthenticationConfiguration, Sitecore.Owin.Authentication">
  <identityProviders hint="list:AddIdentityProvider">
    <identityProvider id="xp0.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>Go To Azure B2C</caption>
      <domain>custom</domain>
      <icon>/sitecore/shell/themes/standard/Images/24x24/msazure.png</icon>
      </identityProvider>
  </identityProviders>
  <propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication">
    <!--List of property mappings
            Note that all mappings from the list will be applied to each providers-->
    <maps hint="list">
      <!--The mapping sets the Email property of the user profile from emailaddress claim-->
      <map name="email" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
        <data hint="raw:AddData">
          <!--claim name-->
          <source name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" />
          <!--property name-->
          <target name="Email" />
        </data>
      </map>          
      <map name="Object Id" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication" resolve="true">
        <data hint="raw:AddData">
          <source name="objectId" />
          <target name="Name" />
        </data>
      </map>
    </maps>
  </propertyInitializer>
  <identityProvidersPerSites>
    <mapEntry name="Custom" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication">
      <sites hint="list">
        <site>MySite</site>
        <site>Portal</site>
      </sites>          
      <identityProviders hint="list:AddIdentityProvider">
        <identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='xp0.azureAD']" />
      </identityProviders>
      <externalUserBuilder type="Foundation.ADB2C.Services.ExternalUserBuilder,Foundation.ADB2C">
        <param desc="isPersistentUser">false</param>
      </externalUserBuilder>       
    </mapEntry>
  </identityProvidersPerSites>
</federatedAuthentication>

IdentityProviderProcessor looks like this:

 protected override string IdentityProviderName => "xp0.azureAD";

    protected override void ProcessCore(IdentityProvidersArgs args)
    {
        Assert.ArgumentNotNull(args, nameof(args));

        var identityProvider = this.GetIdentityProvider();           

        args.App.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        args.App.UseCookieAuthentication(new CookieAuthenticationOptions());
        args.App.UseOpenIdConnectAuthentication(this.CreateOptionsFromPolicy(identityProvider, "B2C_1_login"));
        args.App.UseOpenIdConnectAuthentication(this.CreateOptionsFromPolicy(identityProvider, "B2C_1_registration"));
    }

    private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(IdentityProvider identityProvider, string policy = "B2C_1_registration")
    {
        var authenticationType = this.GetAuthenticationType();
        var options = new OpenIdConnectAuthenticationOptions
        {
            MetadataAddress = string.Format(WellKnownMetadata, Tenant, policy),
            AuthenticationType = policy,
            AuthenticationMode = AuthenticationMode.Passive,
            ClientId = ClientId,
            RedirectUri = RedirectUri,
            PostLogoutRedirectUri = PostLogoutRedirectUri,
            Scope = "openid",
            ResponseType = "id_token",
            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                AuthenticationFailed = this.AuthenticationFailed,
                RedirectToIdentityProvider = notification =>
                {
                    return Task.FromResult(notification.ProtocolMessage.UiLocales = string.Empty);
                },
                SecurityTokenValidated = notification =>
                {
                    notification.AuthenticationTicket.Identity.AddClaim(new Claim("idp", "xp0.azureAD"));

                    // transform all claims
                    ClaimsIdentity identity = notification.AuthenticationTicket.Identity;
                    notification.AuthenticationTicket.Identity.ApplyClaimsTransformations(new TransformationContext(this.FederatedAuthenticationConfiguration, identityProvider));

                    return Task.CompletedTask;
                },
            },

            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "emails",
            },
        };
        return options;
    }

And this is how I trigger a policy from Account Controller:

  [Route("signin")]
    [HttpGet]
    public void SignIn()
    {
        var redirectUrl = "/account";
        if (!this.Request.IsAuthenticated)
        {
            this.HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties() { RedirectUri = redirectUrl }, "B2C_1_login");
            return;
        }

        this.Response.Redirect("/");
    }

Could anyone advise please what I'm missing? Should I create manually a virtual user (we don't want to persist the users), I would have expected this is handled by Sitecore (I might be wrong)?

Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.