allBlogsList

Customizing Sitecore Social Connectors User Creation

Customizing Sitecore Social Connector’s User Creation
written by: Sean Fox, sean.fox@xcentium.com

Before diving in here, I recommend you have a look at the documentation for the Sitecore Social Connector here: https://doc.sitecore.net/social_connected/setting_up_social_connected/configuring/walkthrough_configuring_social_connector_to_work_with_a_social_network

… in case you have any question about it’s setup and configuration.

Scenario:

Sitecore Commerce Server &  Sitecore 8 instance, with Sitecore Social Connector’s “Login For Facebook” being implemented.

When users arrive at the Sitecore Commerce Store, they are presented with an option to login with their Facebook credentials, using the Sitecore Social Connector

When a user successfully logs in through Facebook a user is generated in the Sitecore system for this user the first time they log in. The domain associated with this account out of the box is “default”. For Sitecore Commerce, I would like this to default to “CommerceUsers”.

Having a look around the system, and using reflection on “Sitecore.Social.dll”, I see there are 2 ways to accomplish this … 

1. In “Domains.config” (/App_Include/Security/Domains.config), the “CommerceUsers” domain can be set as the default …

2. Having a look Sitecore.Social.dll, I see that the “CreateUser” pipeline can be altered to achieve the desired result

I opt for the second, wanting to leave the defaults in place in Domains.config. I will end up with a patch file, and a custom class.

Custom patch

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<social.matchUser>
<processor type="[MyAssembly].Configuration.Social.CreateUser, [MyAssembly]" 
patch:instead="processor[@type='Sitecore.Social.Connector.Pipelines.MatchUser.CreateUser, Sitecore.Social']" />
<processor type="Sitecore.Social.Facebook.Connector.Pipelines.MatchUser.FindByFacebookIdsForBusiness, Sitecore.Social.Facebook" 
patch:before="processor[@type='[MyAssembly].Configuration.Social.CreateUser, [MyAssembly]']" />
</social.matchUser>
</pipelines>
</sitecore>
</configuration>

I opt for the second, wanting to leave the defaults in place in Domains.config. I will end up with a patch file, and a custom class. The code for the custom implements the same functionality as out of the box, with the exception of enforcing the “CommerceUsers” domain (always for this operation), and checking for the existence of the user prior to creation.

Custom “CreateUser” class

using System;
using System.Web.Security;
using Ninject;
using Sitecore;
using Sitecore.Diagnostics;
using Sitecore.Events;
using Sitecore.Security.Accounts;
using Sitecore.SecurityModel;
using Sitecore.Social.Connector.Pipelines.MatchUser;
using Sitecore.Social.Infrastructure;
using Sitecore.Social.Infrastructure.Logging;

namespace [MyAssembly].Configuration.Social
{
public class CreateUser
{
public void Process(SelectUserPipelineArgs args)
{
if (args.Result != null || !args.CreateNewUserIfNoExistingFound)
{
return;
}
var fullName = Context.Domain.GetFullName(args.Username);

            var splitter = fullName.Split('\\');
var commerceUserFullName = $"CommerceUsers\\{splitter[1]}"; 
args.Result = CreateSitecoreUser(commerceUserFullName, args.Email, args.AccountBasicData.FullName);
}

        private User CreateSitecoreUser(string domainUser, string email, string fullName)
{
var length = 128;
var numberOfNonAlphanumericCharacters = 20;

            if (Membership.GetUser(domainUser) != null)
{
var membershipUser1 = Membership.GetUser(domainUser);
if (membershipUser1 != null)
return User.FromName(membershipUser1.UserName, false);
}
var membershipUser = Membership.CreateUser(domainUser,
Membership.GeneratePassword(length, numberOfNonAlphanumericCharacters), email);
membershipUser.IsApproved = true;
Membership.UpdateUser(membershipUser);
var user = User.FromName(membershipUser.UserName, false);
try
{
string profileItemId;
using (new SecurityDisabler())
{
profileItemId =
Client.CoreDatabase.GetItem("/sitecore/system/Settings/Security/Profiles/User").ID.ToString();
}
user.Profile.Initialize(user.Name, true);
user.Profile.ProfileItemId = profileItemId;
user.Profile.FullName = fullName;
user.Profile.Email = email;
user.Profile.Save();
}
catch (Exception ex)
{
ExecutingContext.Current.IoC.Get<ILogManager>().LogMessage(ex.Message, LogLevel.Error, this, ex);
}
Event.RaiseEvent("social:connector:user:created", user);
return user;
}
}
}

And that’s it … happy coding.