PHP setcookie "SameSite=Strict"?

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,
    ]);
}

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.example',
    '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.