4
votes

Short Question:

Why doesn't my session cookie's expiry time get updated in the browser when my session's expirty time is updated on the server?

Long Question:

I posted a similar question about this a few weeks ago but I didn't have all of the facts at the time. I now have more detail and the nature of the question has changed so I'm posting it as a new question.

First of all, in CakePHP 2, I've set up APP/Config/core.php with the following for the session:

    Configure::write('Session', array(
        'defaults' => 'database',
        'cookie' => 'mycookie',
        'timeout' => 1 // 1 minute - just for testing
    ));

So, I load a page which in my app which creates the session in the database. All good so far.

The session is stamped to expire at 1341288066 which is equal to Tue, 03 Jul 2012 04:01:06 GMT. Again, this is great because that's 1 minute from now. Exactly what I wanted.

If I look in Firefox's cookie screen, I find the cookie just as I would have expected it:

    Name: mycookie
    Content: aqm0gkmjfsuqje019at8cgsrv3
    Host: localhost
    Path: /
    Send for: Any type of connection
    Expires: Tue 03 Jul 2012 11:01:06 AM ICT  // (04:01:06 GMT)

Now, within this 1-minute window, I go back to my app and refresh the page. Then, I check the session to see if it's updated. It shows 1341288122 against the session id aqm0gkmjfsuqje019at8cgsrv3 which is equal to Tue, 03 Jul 2012 04:02:02 GMT which, again, is what I expected. The expiry of the session has been updated to be 1 minute from when I last reloaded the page.

Unfortunately, the cookie in the browser is still set to Expires: Tue 03 Jul 2012 11:01:06 AM ICT (ie: 04:01:06 GMT) and that's exactly what it does, meaning that the next time I press refresh, Cake generates a brand new session ID even though the old one is still technically valid.

My question is basically what is going on here? Why doesn't the cookie get updated with the new expiry date in the browser?

3
If you are using filesystem for your session date are the folders writable? app/tmp should be writable. - David Yell
@DavidYell The sessions are being updated fine. It's the cookie expiry date on the client machine(s) that isn't being updated. - Joseph
I could reproduce this and would have expected it to work differently, like you. Filed a bug, let's see if we got it all wrong... cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/… - pixelistik
@pixelistik Well, Mark Story has set a milestone for it, so I guess we weren't imagining things :-) Thanks for posting the bug, I wouldn't have been able to explain it that clearly myself. Why don't you go ahead and post an answer to this question to explain that this a shortcoming of CakePHP which will be addressed in 2.3.0 and I'll mark it as the correct answer and award the bounty I promised. - Joseph
@Joseph OK, I tried to wrap it up in an answer. Thanks for spotting this! - pixelistik

3 Answers

4
votes

The issue you have spotted is indeed unexpected and ends sessions where they should stay alive.

This is the result of how CakePHP uses the Session functions of PHP. There is an entry (#3047) in the CakePHP bugtracker, where Mark Story (CakePHP developer) agrees this should be fixed

I can agree that the cookies should be updated alongside the session times stored in the session. However, that's not how PHP's internal features for session handling work. There seem to be a few different ways to workaround this issue.

As this will change the current behavior (however weird it may be), the fix is postponed to version 2.3, though.

I think managing the cookie state outside of PHP is going to be the most appropriate solution. I don't know how safe of a change this is for existing applications though. Changing how sessions works can be dramatic change and allowing users to stay logge din much longer might not be what all developers are expecting.

3
votes

This appears to be how PHP handles sessions. PHP does not update the cookie on each request (see: http://php.net/manual/en/function.session-set-cookie-params.php#100672). Instead of relying on the expiry time in this cookie, CakePHP compares the current time with the actual session timeout in Session::_validAgentAndTime().

0
votes

The problem can be solved by using the two parameters in combination.

Configure::write('Session', array(
    'cookie' => 'CAKEPHP',
    'defaults' => 'php',
    'timeout' => 60,                // 60 minutes: Actual Session Timeout
    'cookieTimeout' => 1440,        // 1440 minutes: 24 hrs: Actual Cookie Timeout
    'autoRegenerate' => true,
    'requestCountdown' => 1,
    'checkAgent' => false,
));
  • autoRegenerate: generates Session Cookie after refresh. The refresh count after which the Session Cookie should be regenerated is determined by the next parameter.
  • requestCountdown: keep the value of this parameter as low as possible. This is the number of refresh/reload after which the Session Cookie will regenerated.