allBlogsList

How to avoid nonsensical usernames when Integrating Sitecore 9dot1 with Active Directory

As we now know Sitecore 9.1 uses Identity Server to handle logins instead of the old methods. Identity is run as a separate app and replaces traditional Sitecore login process. When you install a new instance of Sitecore 9.1 and name it ‘sc910’ for example you’ll see these three folders in your wwwroot:

How to avoid nonsensical usernames when Integrating Sitecore 9.1 with Active Directory

If you are thinking you want to integrate Sitecore Identity Server with Azure Directory, I would recommend first going through Sitecore’s documentation on Sitecore Identity to start with. You can find it here: https://doc.sitecore.com/developers/91/sitecore-experience-manager/en/using-federated-authentication-with-sitecore.html

There are also excellent blog posts out there that you might find very helpful as you go through the integration process. For example, this one is very detailed and super informative: https://sitecore.derekc.net/tag/sitecore-identity/

I’ve recently discovered that there’s one piece in this puzzle that I wish somebody warned me about. When you’ve integrated with AD and your first user signs into a common Sitecore instance at your organization new user is created for them in Sitecore. The login process goes without a hitch and everything works! Exciting! This user locks an item and starts content work. More people join them and work is now in full swing. Some time goes by and then you get a message from your content editor that says “What can be done to help me understand who has a Sitecore item locked? I can see the username but it makes no sense. It’s a bunch of random characters and numbers. I figured I could copy it, go to user manager, search for that username and go from there but it’s so inconvenient!” You login, look at the usernames in User Manager and sure enough they look like this:

How to avoid nonsensical usernames when Integrating Sitecore 9.1 with Active Directory

You are thinking “great! Sitecore is not going to let me rename those unless I directly change them in the database.” And it just doesn’t feel right. Is there a better alternative? There is! You can write code to create usernames that contain either first and last name or user’s email or any combination of the above. Whatever makes sense. Now let’s see what’s needed to make it happen. 

First, we need code. Create your own public class and inherit from DefaultExternalUserBuilder in Sitecore.Owin.Authentication.Services namespace.

public class CreateUniqueUser : DefaultExternalUserBuilder

    {

        public CreateUniqueUser(string isPersistentUser) : base(bool.Parse(isPersistentUser)) { }

        \[SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login")\]

        protected override string CreateUniqueUserName(UserManager<ApplicationUser> userManager,  ExternalLoginInfo externalLoginInfo)

        {

            Assert.ArgumentNotNull((object)userManager, nameof(userManager));

            Assert.ArgumentNotNull((object)externalLoginInfo, nameof(externalLoginInfo));

            IdentityProvider = this.FederatedAuthenticationConfiguration.GetIdentityProvider(externalLoginInfo.ExternalIdentity);

            if (identityProvider == null)

            {

                Log.Error("Error in CreateUniqueUserName: identityProvider is null", this);

                throw new InvalidOperationException("Unable to retrieve identity provider for given identity");

            }           

            string domain = identityProvider.Domain;

            var emailClaim = externalLoginInfo.ExternalIdentity.Claims.FirstOrDefault(x => x.Type == "email");

            if(emailClaim != null)

                return domain + "\\\\" + emailClaim.Value;

            return domain + "\\\\" + "noname";

        }

    }

}

I have tried getting email addresses with externalLoginInfo.Email but it was blank. Not sure where things went wrong but there’s a different way to get to it. We need to dig into claims. Look at the second line of code from the bottom – “domain + “\\” + emailClaim.Value”. That’s what will allows us to use email address as the username.

Next we are going to need a config patch. Let’s pretend you added the class above to a Helix module somewhere in your MySite.Foundation.Extensions. This is what your patch might look like. We need to make sure our mapEntry name is ‘all sites’ and not any other.

<sitecore\>

       <federatedAuthentication\>

            <identityProvidersPerSites\>

                <mapEntry name\="all sites" type\="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication"\>

                    <sites hint\="list"\>

                        <site\>regexp:.\*</site\>

                    </sites\>

                    <externalUserBuilder type\=" MySite.Foundation.Extensions.Pipeline.CreateUniqueUser, MySite.Foundation.Extensions"\>

                        <param desc\="isPersistentUser"\>true</param\>

                    </externalUserBuilder\>

                </mapEntry\>

            </identityProvidersPerSites\>

        </federatedAuthentication\>

</sitecore\>

With these two pieces in place when a new user logs in they’ll get a nice looking username that’s the same as their email. What about existing usernames you might ask? Well, we can easily remove those users and no harm done. Next time they sign in – they are treated as brand new logins and a properly formatted username gets created for them.