A proposal to utilize the Max-Age cookie attribute.
As already described by the title, this RFC proposes that setcookie(), setrawcookie() and ext/session must send the Max-Age attribute alongside Expires when a Set-Cookie header is created.
Currently, there is only one factor that directly affects a user agent's decision of when a cookie should be expired - the Expires attribute. And that would've been fine, if there was a guarantee for both of the following conditions:
Since user agents will calculate the difference based on their own timestamp and the one that they receive, if any of the above two conditions isn't met, then we'll have a problem - the cookie will expire either earlier or later than expected. I can speak from experience, but I'm sure all of you would also understand and agree that this problem is very hard to debug in the rare cases where a client reports it.
Always sending a UTC-based timestamp should give us enough confidence to consider the first condition to always be satisfied. The second one however is never guaranteed and even though we can always blame the problem on a client-side configuration issue - why not just solve the problem once and for all, since a solution is available?
Unlike Expires where a full timestamp is sent, the Max-Age attribute provides a time difference value in seconds (shortly called “TS delta”). A TS delta eliminates the need of the above mentioned conditions, since user agents no longer need to make complex (compared to it) parse and calculation operations.
Instead, they will now need to just add the number of seconds to their local time in order to determine the cookie expiry time. It doesn't matter if they have the right time settings, because that works even for the wrong ones (and it would be more accurate, too!).
The above list makes it pretty clear that the behavior of any user agent that can't take advantage of Max-Age won't be affected. With that said, I believe that it is both safe and proper to send both Expires and Max-Age at the same time, as this will provide a proper fallback for any “legacy” browser that doesn't support Max-Age.
Since setcookie() and setrawcookie() accept a Unix timestamp - the TS delta will have to be calculated based on the provided timestamp, like this:
<max-age> = <provided unix timestamp> - <current time>
ext/session on the other hand will directly send the configured session.cookie_lifetime value, which is exactly the same - TS delta, in seconds.
No downside is expected, except the few more bytes being sent in HTTP headers.
Assuming our current time is: Fri, 28-Dec-2012 03:00:00 GMT
setcookie('name', 'value', 1356663605); // Old header: // Set-Cookie: name=value; expires=Fri, 28-Dec-2012 03:00:05 GMT // New Header: // Set-Cookie: name=value; Expires=Fri, 28-Dec-2012 03:00:05 GMT; Max-Age=5
setrawcookie('name', 'value', 1356663595); // Old header: // Set-Cookie: name=value; expires=Fri, 28-Dec-2012 02:59:55 GMT // New Header: // Set-Cookie: name=value; Expires=Fri, 28-Dec-2012 02:59:55 GMT; Max-Age=-5
session_name('PHPSESSID'); session_set_cookie_params(3600, '/', 'domain.tld'); session_start(); // Old header: // Set-Cookie: PHPSESSID=<random session id>; expires=Expires=Fri, 28-Dec-2012 04:00:00 GMT; path=/; domain=domain.tld // New header: // Set-Cookie: PHPSESSID=<random session id>; Expires=Expires=Fri, 28-Dec-2012 04:00:00 GMT; Max-Age=3600; Path=/; Domain=domain.tld