Virtual Users, custom properties and persisting data
A Virtual User within Sitecore is a transient entity used to represent an authenticated user on your site, unlike a regular user that is persisted within the Sitecore Core database (by default!). A common use-case for this scenario would be if you are using an external system for authentication. A Virtual User allows you to create an authenticated session for that user, without needing to create them in Sitecore. They don’t get fully persisted, and you won’t see them in the User Mananger. However, Sitecore treats them like any other user when it comes to roles + access rules. You’re even able to specify custom properties for virtual users.
Logging in a Virtual User is very straightforward. Here is a typical example for creating a new Virtual User and setting some roles + properties:
LoginVirtualUser is called, an authenticated session is established and on future page requests, the
Sitecore.Context.User will be
A Virtual User is often referred to as an “in-memory” user, suggesting that the user data is held within memory and won’t survive a server restart. This isn’t really true, as we’ll see.
If you are using Forms Authentication, when the
LoginVirtualUser method is called, a standard Forms Authentication cookie is created. By default, this has the name
.ASPXAUTH, and will have an encrypted value such as this:
During an HTTP request, this data is decrypted into a
FormsAuthenticationTicket. In this demo instance, it contains the following data:
This ticket alone is enough for Sitecore to consider the user authenticated as the specified user and allow access to any pages you may have set as restricted to anonymous users.
In the above code example, we added the virtual user into the
extranet\CustomRole role and also added some profile properties. As you can see, this information isn’t found within the ticket. So where is it? Well, note that there is a
UserData property which contains a string,
cj5qfethsr0z4ej1xjxkh4ox. That’s important.
If I take a look at the
Core database for this instance, I find the following row in the
The value of
SessionKey field refers to both the current ASP.NET Session ID and also the
UserData value from the authentication ticket. The
Data field is a Base64 encoding of a serialized
Hashtable object. Within that, is a serialized instance of a
Sitecore.SecurityModel.UserRuntimeSetings object that contains all of the Virtual User data, such as the roles they belong to, and their custom properties.
So as you can see, data is persisted for the Virtual User. Additionally, as the cookie is persisted on the user’s machine, the authenticated user and their data will survive a restart of the web process / server. If you have multiple load-balanced servers referencing the same
Core database, then the Virtual User data will be available to each server, avoiding any load-balancing issues in this particular scenario.
It’s worth noting that this data survives if the ASP.NET Session ID is abandoned. In this instance, the session cookie is removed, but the authentication cookie remains. As this authentication cookie still retains the key within the
UserData property, the data can still be pulled out of the
You should note that the
ClientData table does get cleaned up on a regular basis. There is an agent responsible for this, and that executes every 4 hours by default:
This uses a parameter of the ClientData configuration to determine the
object lifetime, which defaults to 20 minutes. Any rows which have not been accessed within that time in the table will be removed when the agent executes:
So, without changes to this, you shouldn’t treat this storage of Virtual User data as a permenant. But then, it’s not intended to be - generally this would be storage of data you’re only interested in keeping for the duration of the user’s session. If you need something more than this you should look into an alternate method.
The ClientData table has actually been within the Sitecore database for quite some time now, but the use of it to persist Virtual User information is relatively recent. In fact, it was introduced in
Sitecore 8.1 rev. 160302 (8.1 Update-2).
So what happened before then? Well, in earlier versions of Sitecore, the user profile data was actually stored entirely within the authentication cookie:
So, prior to Sitecore 8.1 Update 2, there was no dependency on the
Core database for storing Virtual User profile data. As long as the cookie is in place, the Virtual User would be correctly restored.
That’s what I’ve found from my short dive into Virtual User operations. If you think I’ve stated anything inaccurate, please let me know! I’m going to be looking at this further and into any other common questions around Virtual Users that I see, so if needed I’ll provide a follow-up post with more detail.