Wednesday, 25 March 2015

Chrome doesn't always expire session cookies and what it means for Sitecore DMS

So I was working through an issue with a customer recently and we couldn't work out why a certain behavior was happening and why it appeared to be happening on some browsers and not others. After a bit of digging we discovered that it was to do with the way Chrome manages session cookies.  After solving the specific issue the conversation turned to what does this mean for DMS tracking, particularly with the uptake of chrome in the market.

To put it in context Chrome is becoming pretty popular on the web according to http://gs.statcounter.com/ it is currently sitting at about 49% globally. So any change in the behavior of Chrome can dramatically change the way we need to build solutions.

A session cookie, according to webopedia.com, is: "a cookie that is erased when the user closes the Web browser. The session cookie is stored in temporary memory and is not retained after the browser is closed." This means that traditionally we have been able to set these cookies and assume that they will have expired after the user has closed their browser and won't be present when they come back to the site.

The change that Chrome introduced is it introduced a "Continue where you left off" piece of functionality. When this mode is enabled it aims to provide users the ability to exactly restore their browser to the state it was when they closed it. This includes reinstating any session cookies they had set during their last session. The other point of interest is that this appears to be the default setting on Chrome for mobile.

Now I'm not going to get into the debate of whether its a feature or a bug, or what the security aspects of it are, I'm only interested in how we account for this in the solutions we build.

To put this in context I will use the Sitecore DMS session tracking cookie as an example. Note that I haven't confirmed what versions of Chrome or Sitecore are affected by this, so if you run into this issue please contact Sitecore support. I do know that the issue doesn't exist with Sitecore 7.5 and up as the xDb does not use the same cookie structures as the DMS. Also note that between my writing of this post and when you might be reading it, it is likely that an official patch has been released by Sitecore, so please check release notes or contact Sitecore support.

The Sitecore DMS uses a cookie dropped on a users machine to identify requests that come from a specific session. The information gathered based on the cookie relates to value per visit, page view tracking, time on site, etc. Essentially it is a pretty important piece of information and demonstrates how a seemingly small change in the browser landscape can have unforeseen consequences on web applications.

The way of preventing this from occurring with your cookies is to essentially stop using session cookies and to use a sliding timeout for your cookies instead. The example below is a Sitecore related patch, but the logic can be applied in non-Sitecore related implementations.

In the DMS the visit cookie is set in a place that's not easy to get a hook for, so the easiest way of setting the desired expiry time on the cookie is to update the cookie once the DMS has set it. I have chosen to set this at the end of the "renderLayout" pipeline, which ensures that the DMS has set its values already and won't override anything. It also means that the code will be invoked on every request, which provides the effect of setting a sliding window. The code is as follows:

public class ForceScVisitCookieExpiration
{
    public void Process(PipelineArgs args)
    {
        var context = HttpContext.Current;
        var sessionCookie = context.Request.Cookies.Get("SC_ANALYTICS_SESSION_COOKIE");
        if (sessionCookie != null)
        {
            var timeout = Sitecore.Configuration.Settings.GetIntSetting( "SitecoreVisitExpirationTimeInMinutes", 60);

            sessionCookie.Expires = DateTime.Now.AddMinutes(timeout); 
            context.Response.SetCookie(sessionCookie);
        }
    }
}

All that the code does is retrieve the existing value for the cookie from the request (only needed if you don't have access to where the cookie is being set) and then sets an expiration time for the cookie. This means that the cookie will expire at the designated time, meaning that if a user closes their browser for that period of time, when they come back the cookie will be gone.

The upshot of all of this is that people need to be aware of this behavior in Chrome and that they need to update their solutions to cater for it, whether we like it or not.