Sitecore 9 – How to Authenticate a Virtual User and Identify with xConnect

Posted by

On a recent Sitecore 9 project I had some issues getting Sitecore xConnect to re-associate a virtual user with their xProfile ContactId (Tracker.Current.Session.Contact.ContactId). Every login attempt would produce a different ContactID. Also the user wouldn’t be authenticated, and no “.AspNet.Cookies” cookie was created.

After several hours of trial and error I was able to determine a certain order of events that would cause a user to successfully be authenticated, get the “.AspNet.Cookies” cookie, and be identified with the same ContactID their previous session.

I thought I would share my code to try to save someone else some heart-ache.

Note that I do not know why this particular order of operations work. But the critical piece seems to be setting profile data BEFORE calling AuthenticatedUserRepository.SetAuthenticatedUser(authUser). If you update profile data AFTER calling SetAuthenticatedUser(), or not at all, every login would produce a different ContactId and the user would not be logged in. But if you follow the order below, it will work easy-peasy!

Steps to Login as a Virtual User

  1. Build the virtual user via AuthenticationManager.BuildVirtualUser().
  2. Add the user to a role that will grant access to the restricted pages.
  3. Identify the user with Tracker.Current.Session.IdentifyAs().
  4. Set the user profile properties. (IMPORTANT)
  5. Log in the virtual user.

Here it is all together

// 1. Log the user into Sitecore as a virtual user.
var user = AuthenticationManager.BuildVirtualUser("extranet\\", true);

 // 2. Add user to role to enable access to authentication-required pages
const string roleName = "extranet\\Customer";
if (Role.Exists(roleName))

// 3. Associate the user with their xConnect xDB contact card
if (Tracker.Current != null)
    Tracker.Current.Session.IdentifyAs("extranet", user.Name);

// 4. Assign profile data to the virtual user.
// NOTE IT IS CRUCIAL that the profile code exists and is present BEFORE LoginVirtualUser login to work (so ".AspNet.Cookies" cookie is created)
user.Profile.FullName = "john smith";
user.Profile.Name = user.Name;

// 5. Log the virtual user in.

// Optionally trigger xDB login goal.
GoalsRepository.TriggerGoal(new ID("{66722F52-2D13-4DCC-90FC-EA7117CF2298}"));

Optional: Trigger Login Goal

Sitecore 9 comes with a login goal out of the box, so you can save a few seconds and not have to create your own:

  • Path: /sitecore/system/Marketing Control Panel/Goals/Login
  • ID: {66722F52-2D13-4DCC-90FC-EA7117CF2298}
public static void TriggerGoal(ID goalId)
    Assert.IsNotNull(Tracker.Current, "Tracker.Current");
    Assert.IsNotNull(Tracker.Current.Session, "Tracker.Current.Session");
    Assert.IsNotNull(goalId, "goalId");

    using (var client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
                var reference = new IdentifiedContactReference("xDB.Tracker", Tracker.Current.Session.Contact.ContactId.ToString("N"));
                var actualContact = client.Get(reference, new ContactExpandOptions());
                var userAgent = System.Web.HttpContext.Current?.Request.UserAgent;
                var interaction = new Sitecore.XConnect.Interaction(actualContact, InteractionInitiator.Brand, ChannelIds.OnlineDirectChannelId, userAgent);
                var goal = new Goal(goalId.ToGuid(), DateTime.UtcNow);


Look at all those Goals!

Looking in the experience profile, you can see the crazy number of times I logged in as this user. This means Sitecore successfully recognizes the user across multiple visits. Cool!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s