LoginVirtualUser() details not persisting on a redirect

I am creating a VirtualUser via the following code:

				// generate a user obj
				string username = $"{vDomainName}\\{vProfileInfo.PersonalDetails.Id}";
				Sitecore.Security.Accounts.User virtualUser = Sitecore.Security.Authentication.AuthenticationManager.BuildVirtualUser(username, true);

				// populate user from raw info here

				// Login the virtual user that has been populated with profile info
				returnStatus = Sitecore.Security.Authentication.AuthenticationManager.LoginVirtualUser(virtualUser);
                
                Response.Redirect(returUrl);
                
                //Then on the newly opened page
                Sitecore.Security.Accounts.User virtualUser = Sitecore.Context.User;
                
                // this user has my custom profile values

When I first did this it eventually worked for me and I could retrieve the user details on multiple subsequent pages.

Then I don't know what I did but the login stopped working in that the user details did not persist between page loads.
I spent about a day trying to reverse my code steps to get it back to the situation where it worked but unsuccessfully.

After much head scratching and online searching to no avail, I then resorted to saving the details into a local session var, like this,

Session[SESSION_MEMBERSHIPUSER] = virtualUser;

and then reloading the user on each Page_Init event.

This is not as elegant as I had hoped.

So my question is, when using the AuthenticationManager.LoginVirtualUser(....) method, is this _supposed_ to be saved by Sitecore and for it to persist between page loads?

Under what conditions would this NOT persist?

  • Try to add fixed values to create a virtual user like below, just to ensure that all parameters have been provided correctly.

    namespace Sitecore.Security.Authentication

    Sitecore.Security.Accounts.User user =
    AuthenticationManager.BuildVirtualUser(string.Format(@"{0}\{1}", "Domain", "username"), false);
  • I am also doing the same thing creating virtual user and defining some custom profile values. In my case I can able to persist user information till session timeout or Logout.

    try below code after creating virtual user -

    virtualUser.Profile.Save();
    virtualUser.Profile.Reload();


    Also check after login in any of the place did you use AuthenticationManager.Logout(); code to logout your current user.

    I would suggest you to put Sitecore.Context.User.Identity.Name on your layout section and check after moving from one page to another is it having user data or not?
  • I have implemented Virtual users functionality in one of previous projects and below code may help you!

    Sitecore.Security.Accounts.User user = Sitecore.Security.Authentication.AuthenticationManager.BuildVirtualUser(”domainname\username”, true);

    if (user != null)

    {

    string roleName = “RoleName”;

    //if role exists or not

    if (Sitecore.Security.Accounts.Role.Exists(roleName ))

    {

    //adding user to role

    user.Roles.Add(Sitecore.Security.Accounts.Role.FromName(roleName ));

    }

    Sitecore.Security.UserProfile profile = user.Profile;

    profile.FullName = userRole;

    profile.Save();

    // logging virtual user to Sitecore and this is a temporary session

    Sitecore.Security.Authentication.AuthenticationManager.Login(user);

    you can find an article on it

    Regards,

    Praveen Chidaboyina

    Sitecore Certified Developer| Blog

  • I trialled a few of the techniques listed and eventually discovered that I was mostly right and where I was wrong.

    The wrong part was that one line I commented out which was where I was populating the newly created virtual user. Something I did there caused a problem with the virtual user object.

    I trimmed the code down to this barebones listing. Doing it this way meant that it worked properly.

    // created username in old way just to see if anything changed, didnt
    string username = String.Format(@"{0}\{1}", vDomainName, vProfileInfo.PersonalDetails.Id);
    Sitecore.Security.Accounts.User virtualUser = Sitecore.Security.Authentication.AuthenticationManager.BuildVirtualUser(username, true);
    // manual population 
    virtualUser.Profile.FullName = username;
    virtualUser.Profile.Save();
    // login
    returnStatus = Sitecore.Security.Authentication.AuthenticationManager.LoginVirtualUser(virtualUser);
    
    // redirect to new page
    this.Controller.LoginUser(Sitecore.Context.User); // now populated
    

    So all I have to do now is work out a nice way to populate my virtual user without losing whatever critical detail it needs.

    Interestingly, it didnt seem to matter if I used AuthenticationManager.Login(user) or AuthenticationManager.LoginVirtualUser(user).

    Thanks to everyone for their suggestions.

  • In reply to AJ Murray:

    Further to my explanation above, after further experimentation I have encountered various other problems when dealing with a VirtualUser.

    It is not apparently possible to inherit from the Sitecore.Security.Accounts.User, nor usefully from the UserProfile object.

    It is not possible to create an new UserProfile object, populate it and then assign it to the virtualuser.Profile property due to that property being Get only.

    Passing the virtualUser.Profile value into a function for population also didn't seem to work again the logged in user was not then persisted.

    I then created a single function that did all the work thus:

    BuildVirtualUser()

    Set all the profile properties and custom properties. (Did NOT Profile.Save(). Doesnt seem to need this.)

    LoginVirtualUser()

    Then I did some tedious trial and error with minimalist setting of the properties, checking that it worked, and then gradually including one more in successive tests. checking that the user was persisted each time.

    This revealed that I could set properties of the VirtualUser.Profile directly, such as Profile.Email, Profile.FullName. User still was persisted.

    Then I went from 1 customproperty to 10 customproperty settings. It failed on the 10th one.

    I changed the order, moved lines around, and other things, still seemed like it would save 9 but not 10.  None of the property values are longer than about 15 chars.

    Looks like I will have to go back to my Session var to save required values persistently. 

  • In reply to AJ Murray:

    Well my workaround is now this.

    BuildVirtualUser(), set minimal profile details.

    LoginVirtualUser()

    BuildVirtualUser() again, set all my required custom profile properties

    Save second user to Session var.

    Redirect to returnUrl.

    On new page load, check Context.User.IsAuthenticated. This is now true from first login effort. 

    Load fully populated user from Session var.

     

    Not perhaps ideal but it works. Have wasted enough time. Sometimes you just have to move on.......

  • In reply to AJ Murray:

    I also came across with same issue and below are my findings I am posting here so in case any one else is facing the same issue he can have a look and make the changes -

    I recently came across with the same situation where we have created Virtual user and also created some custom property. At the early stage it was working properly as Sitecore user works but one day suddenly it stopped working.

    In my solution still Sitecore.Context.User.IsAuthenticated this was always true but all the profile properties was empty at this time. Then I started digging into our latest change we made for project and found we just added a view rendering on LogIn page (Login Item). And that rendering was having

    var customPropValue = Sitecore.Context.User.Profile.GetCustomProperty("customProp");


    code and some other code too.

    To just test I removed the rendering from the login item and it seems functionality again started working because after login it was either redirecting me to home page or RedirectURL page.

    Then it was proved that Virtual user was not working because of the new rendering which contains code to get custom property of user. I again applied that rendering to item and this time I removed all other code from the rendering and still keep

    var customPropValue = Sitecore.Context.User.Profile.GetCustomProperty("customProp");


    code into it and this time again issue was same I lost all the profile properties of virtual user.

    At last I removed the

     

    var customPropValue = Sitecore.Context.User.Profile.GetCustomProperty("customProp");


    code from the rendering and it started working for me.

    I want that code on other pages but not on login page so I added a condition on top if page is login page then don't execute this code and execute for all other pages. After making this change it started working for me.

    On the other pages I was using same code so there was no issue with the code I found that issue is with the code on Login page. After login and redirect user on any page everything works perfect in virtual user.

    I already opened a ticket in Sitecore for same they are looking into the same why it is not working if we are getting any profile properties at the time of login.

    We have tested this Virtual user functionality with multiple login at the same time and it is working perfect.

  • I encountered this and have managed to boil it down to a simple reproducable bug which I have raised with Sitecore


    Add these 2 aspx files to the root of the site:


    VirtualUser1.aspx

    <%@ Page Language="C#" AutoEventWireup="true" %>
    <%@ Import Namespace="Sitecore" %>
    <%@ Import Namespace="Sitecore.Security.Authentication" %>
    <script runat="server">
    public void Page_Load(object sender, EventArgs e)
    {
    var virtualUser = AuthenticationManager.BuildVirtualUser("extranet\\testvirtualuser", true);
    virtualUser.Profile.SetCustomProperty("CustomPropertyName", "CustomPropertyValue");
    AuthenticationManager.LoginVirtualUser(virtualUser);
    Response.Redirect("VirtualUser2.aspx");
    }
    </script>




    VirtualUser2.aspx

    <%@ Page Language="C#" AutoEventWireup="true" %>
    <%@ Import Namespace="Sitecore" %>
    <%@ Import Namespace="Sitecore.Security.Authentication" %>
    <script runat="server">
    public void Page_Load(object sender, EventArgs e)
    {
    var loggedInUser = AuthenticationManager.GetActiveUser();
    var propertyVal = loggedInUser.Profile.GetCustomProperty("CustomPropertyName");
    Response.Write(propertyVal);
    }
    </script>




    1. Clear cookies
    2. Go to VirtualUser1.aspx. You will be redirected to VirtualUser2 aspx and the screen will display "CustomPropertyValue"
    3. Clear cookies again
    4. Go to VirtualUser1.aspx. You will be redirected to VirtualUser2 aspx and the screen will display nothing.
    5. Clear cookies again
    6. Go to VirtualUser1.aspx. You will be redirected to VirtualUser2 aspx and the screen will display "CustomPropertyValue"

  • Hello has there been any new development on this issue please and was there a ticket logged for it please?