PHP session cookie problems with Google Chrome and Internet Explorer

In this post, I describe two potential pitfalls with handling session cookies in Google Chrome and Internet Explorer while developing websites, and how to avoid them. The problem in Google Chrome relates to its handling of local/internal hostnames, and the problem in Internet Explorer relates to its privacy settings and compact privacy policies.

Today I spent some time cross-browser testing a PHP app. I do all my basic testing in Firefox, as that's my browser of choice, but of course sites have to be tested in other browsers before live rollout. Normally this doesn't cause any problems, except for the usual complaints about Internet Explorer's (lack of) standards compliance, but this time I ran into a couple of problems with session management.

As you'll probably be aware (since you're reading this article), sessions are a handy way of keeping track of user information across different pages. A common use case, and the one that inspired this article, is checking whether a user is logged in, and displaying content accordingly.

Sample PHP code to set a session cookie

In keeping with best practice, I usually initialise sessions like so:

ini_set('session.use_trans_sid', false);
ini_set('session.use_cookies', true);
ini_set('session.use_only_cookies', true);
$https = false;
if(isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] != 'off') $https = true;
$dirname = rtrim(dirname($_SERVER['PHP_SELF']), '/').'/';
session_name('some_name');
session_set_cookie_params(0, $dirname, $_SERVER['HTTP_HOST'], $https, true);
session_start();

These settings ensure that sessions are tracked via cookies rather than $_GET parameters, that they are restricted to the site domain and directory only, and that they are protected from JavaScript access. Obviously these settings aren't appropriate for all sites, but for applications that are deployed into a single subdirectory on a server, they make pretty good sense.

Google Chrome session cookie problem

The first problem I discovered was the $_SERVER['HTTP_HOST'] part. For simplicity's sake, I carry out my testing by running a web server and browser on the same machine, via localhost, hence $_SERVER['HTTP_HOST'] evaluates to localhost. Fine? I thought so, and so did Firefox. Unfortunately, Chromium didn't agree. The session wasn't started in Chromium, and I couldn't log in to the app. Thankfully the fix was fairly straightforward.

Lesson 1:
When testing a local site in Chromium, you must either access it via IP address (e.g. 127.0.0.1) or set the cookie domain parameter to the empty string.

Easy enough to do, if annoying. On to the next problem...

Internet Explorer session cookie problem

As I mentioned earlier, I'd also been having problems with Internet Explorer during my testing. Unfortunately, as my dev system runs Linux, to test with IE I had to use a Windows VM install, and therefore I was accessing the site via IP address rather than localhost. Consequently, it was clear that this was due to a different problem. When I searched the internet, it seemed that most people experiencing similar problems were using test domains that use an underscore _ character in them, in violation of RFC 1035. Since (a) I know this isn't allowed, and (b) I wasn't using a domain name at all, I knew this wasn't the cause of the problem. Some other people suggested client/server timezone differences as a possible cause. Again, this wasn't the case with my app. The root cause actually turned out to be related to privacy settings, but when I did stumble across the correct answer I didn't immediately realise it was correct.

Lesson 2:
When testing in Internet Explorer, either make sure that the privacy setting for your test site is Medium High or lower, OR set a P3P header in your code.

I managed to get the test site working by lowering my Internet Explorer privacy settings from High to Medium High. While doing so, I noticed that the main difference between the two is only cookies with a compact privacy policy are allowed when the privacy is set to High, apparently even when they're just session cookies. When I discovered that this worked, I wondered what constitutes a "compact privacy policy". It turns out that it's a string of characters that either go in the HTTP headers or in the HTML . The process of setting it up is both complicated and boring, so I won't go into it here. Suffice to say that I think it's simpler just to turn down the privacy settings. If you really want to use a P3P header instead, put the following snippet before you set your session cookie (and before you output any HTML):

header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

N.B. You shouldn't use this snippet on a public site! Instead, you should head to http://www.w3.org/P3P/usep3p.html and follow the instructions there to set up a privacy policy that's specific to your site.

Comments

Anonymous - Sun, 16/06/2013 - 05:56

Permalink

Thanks for this post, it really worked for me, after lot of search, finally it works for me. Thank you So much :)

Anonymous - Wed, 07/08/2013 - 21:40

Permalink

I was testing my website on Chrome, but session authentification with cookie wouldn't work... I accessed with 127.0.0.1 and it had solved the problem.

Thanks a lot!

VITOR HUGO - Wed, 13/12/2017 - 10:40

Permalink

Yes! Funcionou perfeitamente depois de muito tentar! Parabéns!

VITOR HUGO - Wed, 13/12/2017 - 10:41

Permalink

YES! YES! YES! YES! YES! YES! YES! YES! YES!

It´s WORK!

In your Lesson 1: "... or set the cookie domain parameter to the empty string."... How? Where? Where is this cookie domain parameter? Front-end / Back-end? And how to set it? And what to set it to?

Hello Noel, apologies for the delayed reply. You need to set it in backend code. In the PHP-based example above, this is the relevant line: session_set_cookie_params(0, $dirname, $_SERVER['HTTP_HOST'], $https, true);. You need to set the third parameter to the empty string, for example session_set_cookie_params(0, $dirname, '', $https, true);. Note that in the years since this article was originally written, there is also an alternative format for the session_set_cookie_params() PHP function. See the official documentation for the specifics. If you need to set the samesite cookie attribute, which is recommended for many secure sites, you will need to use the new format.

Add new comment

CAPTCHA