====== Request for Comments: Cookie Max-Age attribute ====== * Version: 1.1 * Date: 2012-12-28 * Author: Andrey Andreev * Status: Implemented * First Published at: http://wiki.php.net/rfc/cookie_max-age A proposal to utilize the Max-Age cookie attribute. ===== Introduction ===== 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. ==== Why is it needed? ==== 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: - User agents always parse the timestamp correctly. - User agents always have correct time settings. 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? ==== How does it help? ==== 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!). ===== Technical details and considerations ===== * A zero (0) value means that the cookie must be immediately dropped (as should any negative value). * The //Max-Age// attribute is unfortunately, not supported by all user agents. This is natural, since it is relatively new. * User agents that don't support it should ignore it (as with any other unrecognized cookie attribute). * User agents that do support it must give it a higher precedence and will practically ignore //Expires//. 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//. ==== Logical behavior ==== Since **setcookie()** and **setrawcookie()** accept a Unix timestamp - the TS delta will have to be calculated based on the provided timestamp, like this: '' = - '' **ext/session** on the other hand will directly send the configured **session.cookie_lifetime** value, which is exactly the same - TS delta, in seconds. ==== Possible BC effects ==== No downside is expected, except the few more bytes being sent in HTTP headers. ===== Examples ===== 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=; expires=Expires=Fri, 28-Dec-2012 04:00:00 GMT; path=/; domain=domain.tld // New header: // Set-Cookie: PHPSESSID=; Expires=Expires=Fri, 28-Dec-2012 04:00:00 GMT; Max-Age=3600; Path=/; Domain=domain.tld ===== Related links ===== * [[https://github.com/php/php-src/pull/238|Pull request on GitHub]] (I am not an experienced C coder, please feel free to improve or write an alternative) * [[https://bugs.php.net/bug.php?id=23955|Bug #23955]] * [[https://bugs.php.net/bug.php?id=43439|Bug #43439]] * [[http://www.ietf.org/rfc/rfc2109.txt|RFC 2109]] * [[http://www.ietf.org/rfc/rfc2965.txt|RFC 2965]] * [[http://www.ietf.org/rfc/rfc6265.txt|RFC 6265]] ===== Changelog ===== * 2012-12-28: Updated with suggestions from the thread on PHP-Internals. * 2012-12-28: Initial version.