Same-Site Cookies

HTTP is a stateless protocol, so technically each request is independent of its predecessors and successors. Websites and web applications need to recognize their users, however asking them to type in their username and password on every page is certainly not an option. Enter HTTP sessions, and cookies, as we all already know.

With the growth of the web, it became less and less a friendly place - and we are not necessarily talking about people here, but more about bots, and scripts. So in recent years, a lot of improvements have been made to increase security, and provide a better protection of privacy.

This leads to a growing number of optional arguments to functions like session_set_cookie_params(), which is hard to read and is error-prone. With PHP 7.3, an alternative way to pass parameters has been introduced, namely a parameter array.

Rather than doing

session_set_cookie_params(3000, '/', 'example.com', true, true);

var_dump(session_get_cookie_params());

and asking yourself questions like “does the first true mean ‘secure’ or ‘httponly’?”, which will not even be answered by looking at the output:

array(6) {
  ["lifetime"] => int(3000)
  ["path"] => string(1) "/"
  ["domain"] => string(11) "example.com"
  ["secure"] => bool(true)
  ["httponly"] => bool(true)
  ["samesite"] => string(0) ""
}

you can now also write

session_set_cookie_params(
    [
        'lifetime' => 3000,
        'path' => '/',
        'domain' => 'example.com',
        'secure' => true,
        'httponly' => true
    ]
);

To increase protection against Cross Site Request Forgery attacks, you can set samesite to true. You can also pass an options array to setcookie() and setrawcookie(), which of course also includes the samesite attribute. Unfortunately, things are not as easy as just making every single cookie a SameSite cookie, but it seems that for session cookies, there is really no reason not to.

Remember to call session_set_cookie_params() before calling session_start(), otherwise the session cookie has already been sent (or, at least, been scheduled to be sent) with the default settings.