Lasso

Conquering Internet Explorer Double Cookie Madness


A while ago my company experienced a weird problem where users were logging into a system we’d built for a client and yet -inexplicibly- then told them they could not view their content because they were not logged in.

The common theme: every affected user was using Internet Explorer, but that wasn’t the whole story.

Microsoft Internet Explorer is the browser we all love to hate – and in some cases for good reason. Yeah, I know MSIE pre-9 was really flakey, and I was prepared to write it off as a “this is weird, but get with the program and upgrade your browser” situation.

However I then managed to replicate it on IE 9, so I was forced to dig deeper. What I found was mighty frustrating, and it’s gotta be biting anyone that is using session management plus redirecting traffic to a single domain for good SEO (i.e. avoiding the trap of Google’s algorithm’s and their duplicate content penalties).

 

Scenario

  • Joe Bloggs uses MSIE v.X as his every day browser (please no jokes I’m being serious here).
  • Joe visits http://mygreatdomain.com
  • The system’s doing SEO best practice and the server redirects to the www verison of the site.

Here’s the catch: In some cases you want to do redirection in code, because there’s some pre-filtering or geographic executions etc – and as part of that you’re starting a session… and using a cookie. So there’s a cookie set on http://mygreatdomain.com, no big deal. But when the browser’s redirected to http://www.mygreatdomain.com some really funky stuff can start to happen.

On every other browser we could find the cookie from the non-www is not sent to the server as part of the header request to the server.

 

MSIE’s Double-Cookie Madness

MSIE (at least up to and including 9) sends both back to the server.

Owch. Major headaches. Generally session managers just take the first session of a given name and use that. But if the “real” session is the second in the array it’s always going to be wrong: when the state changes and a write back to the browser is made it will be on the wrong domain.

To put it another way:
Logins just won’t stick because the read and writes seem to be going to different cookie linked sessions.

 

Code time.

This code below shows the first hit on the non-www domain.

[session_start('test', -expires=360,-usecookie=true,-useauto=false)]
<p>Host: [web_request->httpHost]</p>
<p>Cookies: [web_request->cookies]</p>

>> Result
Host: mygreatdomain.com
Cookies: staticarray((_LassoSessionTracker_test = f236a937-8eb6-4a56-a0d5-c15f3f87aa30))

Now lets add in the redirect.

[
session_start('test', -expires=360,-usecookie=true,-useauto=false)
not(web_request->httpHost >> 'www') ? redirect_url('http://www.'+web_request->httpHost)
]
<p>Host: [web_request->httpHost]</p>
<p>Cookies: [web_request->cookies]</p>

>> Result
Host: www.mygreatdomain.com
Cookies: staticarray(
    (_LassoSessionTracker_test = 8e19fdb2-d285-411e-a17a-1b3d6d01cedd), 
    (_LassoSessionTracker_test = 8e19fdb2-d285-411e-a17a-1b3d6d01cedd)
)

So what’s happened?

The browser hit http://mygreatdomain.com, the session got started plus the session cookie gets set (we’d do our prefiltering or whatever we wished). It was redirected to www.mygreatdomain.com, and the session gets started again – losing the linked session so a new one gets started. However, MSIE in it’s infinite wisdom, then sends back both cookies to the server with subsequent requests.

 

The solution

The situation can be solved in one of two ways.

Firstly, avoidance. In many situations it’s going to be practical to structure it in such a way that the session_start goes after the redirect – problem solved. There’s an effective abort of code immediately after the redirect so the session never gets started and MSIE will never get told to set a cookie.

However that’s not always practical. Fortunately the fix is quite simple – take the nuclear option on the cookie.

[
session_start('test', -expires=360,-usecookie=true,-useauto=false)
if(not(web_request->httpHost >> 'www')) => {
	Cookie_Set(
		'_LassoSessionTracker_test'='',
		-Domain=web_request->httpHost->asString,
		-Expires='-1',
		-Path='/'
	)
	redirect_url('http://www.'+web_request->httpHost)
}
]
<p>Host: [web_request->httpHost]</p>
<p>Cookies: [web_request->cookies]</p>

>> Result
Host: www.mygreatdomain.com
Cookies: staticarray((_LassoSessionTracker_test = f236a937-8eb6-4a56-a0d5-c15f3f87aa30))

This result is achieved by hitting http://mygreatdomain.com, it gets session start, cookie death, and then the redirect to the www, and you can see there’s only one cookie, and all is well in the world.

MSIE clients can now use the site and keep a logged in state.