PHP setcookie "SameSite=Strict"?
1. For PHP >= v7.3
You can use the $options
array to set the samesite
value, for example:
setcookie($name, $value, [ 'expires' => time() + 86400, 'path' => '/', 'domain' => 'domain.com', 'secure' => true, 'httponly' => true, 'samesite' => 'None',]);
The value of the samesite element should be either None
, Lax
or Strict
.
Read more in the manual page.
2. For PHP < v7.3
You can use one of the following solutions/workarounds depending on your codebase/needs
2.1 Setting SameSite cookies using Apache configuration
You can add the following line to your Apache configuration
Header always edit Set-Cookie (.*) "$1; SameSite=Lax"
and this will update all your cookies with SameSite=Lax
flag
See more here: https://blog.giantgeek.com/?p=1872
2.2 Setting SameSite cookies using Nginx configuration
location / { # your usual config ... # hack, set all cookies to secure, httponly and samesite (strict or lax) proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";}
Same here, this also will update all your cookies with SameSite=Lax
flag
See more here: https://serverfault.com/questions/849888/add-samesite-to-cookies-using-nginx-as-reverse-proxy
2.3 Setting SameSite cookies using header
method
As we know cookies are just a header in HTTP request with the following structure
Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax
so we can just set the cookies with header
method
header("Set-Cookie: key=value; path=/; domain=example.org; HttpOnly; SameSite=Lax");
In fact, Symfony is not waiting for PHP 7.3 and already doing it under the hood, see here
📝You can use same in Laravel too because Laravel under the hood using Symfony's Symfony\Component\HttpFoundation\Cookie
class
2.4 Setting SameSite cookies using a bug in setcookie
method
setcookie('cookie-name', '1', 0, '/; samesite=strict');
Be careful with this one, it's a known bug in PHP setcookie
method and already resolved in PHP7.3 version, see here - https://github.com/php/php-src/commit/5cb825df7251aeb28b297f071c35b227a3949f01
[Important update: As @caw pointed out below, this hack WILL BREAK in PHP 7.3. Stop using it now to save yourself from unpleasant surprises! Or at least wrap it in a PHP version check like if (PHP_VERSION_ID < 70300) { ... } else { ... }
.]
It seems like you can abuse the "path" or "domain" parameter of PHP's "setcookie" function to sneak in the SameSite attribute because PHP does not escape semicolons:
setcookie('samesite-test', '1', 0, '/; samesite=strict');
Then PHP sends the following HTTP header:
Set-Cookie: samesite-test=1; path=/; samesite=strict
I've just discovered this a few minutes ago, so please do your own testing! I'm using PHP 7.1.11.
Based on Steffen's answer above, this is the method I am using to support both php <= 7.2 and php >= 7.3:
/** * Support samesite cookie flag in both php 7.2 (current production) and php >= 7.3 (when we get there) * From: https://github.com/GoogleChromeLabs/samesite-examples/blob/master/php.md and https://stackoverflow.com/a/46971326/2308553 * * @see https://www.php.net/manual/en/function.setcookie.php * * @param string $name * @param string $value * @param int $expire * @param string $path * @param string $domain * @param bool $secure * @param bool $httponly * @param string $samesite * @return void */function setCookieSameSite( string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly, string $samesite = 'None'): void { if (PHP_VERSION_ID < 70300) { setcookie($name, $value, $expire, $path . '; samesite=' . $samesite, $domain, $secure, $httponly); return; } setcookie($name, $value, [ 'expires' => $expire, 'path' => $path, 'domain' => $domain, 'samesite' => $samesite, 'secure' => $secure, 'httponly' => $httponly, ]);}