Recently, I ran into a problem with an image gallery web application I am writing in PHP. Throughout development, which was done on my Windows laptop using XAMPP, everything worked perfectly fine, both on Firefox as well as Internet Explorer.
As soon as I deployed my application on my Linux server, IE suddenly stopped accepting my session cookies. The weird thing was that Firefox continued to work perfectly fine.
My application makes multiple AJAX requests to render each page. Usually, a single session would get created and each subsequent request would reuse that session. Instead, each request was creating a new session. My application didn’t work at all since session variables were no longer accessible. On the server side, the PHP session directory was getting flooded with session files.
I didn’t see any cookies for my application in IE’s cache directory. For every request that IE was making, PHP was creating a new session and IE was rejecting the session cookie returned. Hence, there was no session cookie to send back to the server for the next request and PHP was assigning a new session for each request.
Considering everything worked fine on Firefox but not on IE, one would think it was some bug in my application. But it worked fine in IE when running on the Windows laptop. So there was probably nothing wrong with my application.
Google turned up a couple relevant results after a lot of searching. Here’s what I found:-
As per this website, IE 6 had a new feature that would reject sessions in certain circumstances unless a specific header was sent clarifying the intentions of the web appliction. This seemed probable so I gave it a try.
I added the following to the top of my application so that every call would return this HTTP header:-
header('P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
It didn’t work so it was something else.
Session IDs transported by URL
This website claimed that the latest IE update increased the security levels and that applications had no choice but to hard code the session IDs in the URLs. This can be done by enabling the following option in php.ini:-
session.use_trans_sid = 1
Of course, this meant that every URL needed to have the session ID added to it. It didn’t feel like the right option since Microsoft wouldn’t break web applications so badly. Considering how many URLs each application has and how many applications are out there, it would be prohibitive to have to change them all to include a session ID.
A third website suggested that IE was calculating session cookie timeouts incorrectly such that they seemed to expire in the past. As a result, these already expired cookies were rejected immediately. For example, if the server was in Hawaii and the client in Australia and the server requested a session timeout of one hour, the timeout would have already occurred as far as the client in Australia was concerned.
Firefox didn’t have this issue since it converts both the server as well as the client time to UTC and then calculates the timeout. As interesting as this was, this didn’t seem as the problem since both my laptop client as well as my server were in the same timezone.
The timezone issue did give me a hint to check the time on my client and server. My client is a Windows laptop which had the correct time and timezone thanks to being synchronized with the NTP protocol. My server on the other hand was out of sync.
The timezone was correct, but the UTC time was set to my local time instead. As a result, the server was actually six hours in the past as far as the client was concerned. A timeout of one hour would have expired in the past for an IE instance running on my client. No wonder IE was rejecting my sessions.
I ran ntpdate to fix my time and then reset my timezone using tzselect.
# ntpdate pool.ntp.org
I then refreshed IE which immediately started accepting the sessions. All aspects of my application started working correctly. So much for so little.
Moral of the story, use NTP to ensure that your machines have their time set correctly.