Populate Actual User Names on UserManager While integrating Azure AD with Sitecore

Historically, monolith versions of Sitecore have used the ASP.NET membership to validate and Store User credentials. With a major architecture change from Sitecore 9, it uses what is referred to as ASP.NET Identity. ASP.NET Identity makes use of Owin middleware components to support external authentication providers. These external providers allow federated authentication within the Sitecore XP. In this context, if you also observe the latest Sitecore installations you would end up seeing below three folders, one of them being IdentityServer.

Azure AD with Sitecore local instance folder snapshot

Sitecore uses this Identity Server as a separate App to handle user logins instead of the traditional method.

If you are new to Azure AD and want to integrate it into your Sitecore instance, the recommendation is to always go through Sitecore’s documentation on Sitecore identity.

Use Federated Authentication with Sitecore Documentation

So during the integration of Azure AD to Sitecore 10, I was able to follow documentation and configure easily and could verify Sitecore AD user was able to log in. The process was easy-peasy. But then after some testing, I did see the unexpected results on UserManager which is randomized alphanumeric characters as Usernames who have successfully logged in.

Azure AD integration with Sitecore user manager users snapshot

Oh no !!! For a second I thought I might have to script it to update them in DB which is not what I really wanted to do.

Feeling when you tried to Populate Actual User Names on UserManager While integrating Azure AD with Sitecore

At this moment I wasn’t feeling right about the situation, and after going through some slack chats and googling, yes there is an alternative for it and that’s by writing our own “ExternalUserBuilder“. No Fear we would just need to write a bit of code and a bit of configuration in order to utilize our code.

Configuring Custom User Builder

The overview of this code is to extend the default user builder and get our custom code which checks for email, username, and domain and retrieves the same to be shown on User Manager instead of randomized characters. For the below code ( Gist Link ) you would need to inherit from DefaultExternalUserBuilder which resides in “Sitecore.Owin.Authentication.Services” namespace.

public class CustomExternalUserBuilder : DefaultExternalUserBuilder
    {
        public CustomExternalUserBuilder(string isPersistentUser) : base(bool.Parse(isPersistentUser)) { }
        protected override string CreateUniqueUserName(UserManager userManager, ExternalLoginInfo externalLoginInfo)
        {
            Assert.ArgumentNotNull((object)userManager, nameof(userManager));
            Assert.ArgumentNotNull((object)externalLoginInfo, nameof(externalLoginInfo));
            identityProvider = this.FederatedAuthenticationConfiguration.GetIdentityProvider(externalLoginInfo.ExternalIdentity);
            string defaultDomain = "sitecore\\";
            if (string.IsNullOrWhiteSpace(externalLoginInfo.Email))
            {
                if (identityProvider != null)
                {
                    defaultDomain = identityProvider.Domain;
                    var emailClaim = externalLoginInfo.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == "email");
                    if (emailClaim != null) return defaultDomain + "\\" + emailClaim.Value;
                }
                
                var validUserName = externalLoginInfo.DefaultUserName.Replace(",", "").Replace(".", "").Replace("'", "");
                return defaultDomain + validUserName.Replace(" ", "");
            }
            return defaultDomain + externalLoginInfo.Email;
        }
    }

Just to make sure we always have some value, I am checking for Email from externalLoginInfo, some cases if this is empty we have another way of digging it from claims type email. If both conditions fail then we pick DefaultUserName.

Patch Config

Before everything starts working we would need below patch config file. Let’s assume you added the above class under BasicCompany -> Foundation -> Extensions -> UserBuilders . So you end up providing type as BasicCompany.Foundation.Extensions.UserBuilders.CustomExternalUserBuilder and project namespace as BasicCompany.Foundation.Extensions

<sitecore>
    <federatedAuthentication>
        <identityProvidersPerSites>
            <mapEntry name="all sites" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication" resolve="true">
                <sites hint="list">
                    <site>regexp:.*</site>
                </sites>
                <externalUserBuilder type="BasicCompany.Foundation.Extensions.UserBuilders.CustomExternalUserBuilder, BasicCompany.Foundation.Extensions" resolve="true">
                    <IsPersistentUser>true</IsPersistentUser>
                </externalUserBuilder>
            </mapEntry>
        </identityProvidersPerSites>
    </federatedAuthentication>
</sitecore>

Once these two are in place, our problem is solved as any new users who log in will be created with a proper username/email. So now comes another thought of how about existing usernames who have randomized characters as usernames?

It’s very simple and straightforward, just go ahead and delete all Users (manually or from SQL script) who have this issue, as there will be no harm done and the user gets created with proper usernames next time they log in as you can see the result below.

Result of Populating Actual User Names on UserManager While integrating Azure AD with Sitecore snapshot

Whatever you see here also depends on how users’ properties have been configured in Sitecore identity Server Azure AD configuration.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *