diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index 89953502ba76..624deb0283fd 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -25,6 +25,7 @@ class RememberMeFactory implements SecurityFactoryInterface 'domain' => null, 'secure' => false, 'httponly' => true, + 'samesite' => null, 'always_remember_me' => false, 'remember_me_parameter' => '_remember_me', ]; diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index fba79fba874e..53b63689739e 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -38,6 +38,7 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface protected $options = [ 'secure' => false, 'httponly' => true, + 'samesite' => null, ]; private $providerKey; private $secret; @@ -281,7 +282,7 @@ protected function cancelCookie(Request $request) $this->logger->debug('Clearing remember-me cookie.', ['name' => $this->options['name']]); } - $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'])); + $request->attributes->set(self::COOKIE_ATTR_NAME, new Cookie($this->options['name'], null, 1, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'], false, $this->options['samesite'])); } /** diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index 272a5cc2db1c..94ec0eae53dd 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -84,7 +84,9 @@ protected function processAutoLoginCookie(array $cookieParts, Request $request) $this->options['path'], $this->options['domain'], $this->options['secure'], - $this->options['httponly'] + $this->options['httponly'], + false, + $this->options['samesite'] ) ); @@ -117,7 +119,9 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt $this->options['path'], $this->options['domain'], $this->options['secure'], - $this->options['httponly'] + $this->options['httponly'], + false, + $this->options['samesite'] ) ); } diff --git a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php index 3df2ced6223f..32e65f3cf0b0 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php @@ -81,7 +81,9 @@ protected function onLoginSuccess(Request $request, Response $response, TokenInt $this->options['path'], $this->options['domain'], $this->options['secure'], - $this->options['httponly'] + $this->options['httponly'], + false, + $this->options['samesite'] ) ); } diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php index 599a7e81c303..7afa48edc950 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentTokenBasedRememberMeServicesTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Security\Http\Tests\RememberMe; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; @@ -268,7 +269,7 @@ public function testLoginFail() public function testLoginSuccessSetsCookieWhenLoggedInWithNonRememberMeTokenInterfaceImplementation() { - $service = $this->getService(null, ['name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true]); + $service = $this->getService(null, ['name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'samesite' => Cookie::SAMESITE_STRICT, 'lifetime' => 3600, 'always_remember_me' => true]); $request = new Request(); $response = new Response(); @@ -305,6 +306,7 @@ public function testLoginSuccessSetsCookieWhenLoggedInWithNonRememberMeTokenInte $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610); $this->assertEquals('myfoodomain.foo', $cookie->getDomain()); $this->assertEquals('/foo/path', $cookie->getPath()); + $this->assertSame(Cookie::SAMESITE_STRICT, $cookie->getSameSite()); } protected function encodeCookie(array $parts) diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php index f24e4fff8080..4a34d614213f 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/TokenBasedRememberMeServicesTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Security\Http\Tests\RememberMe; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; @@ -205,7 +206,7 @@ public function testLoginSuccessIgnoresTokensWhichDoNotContainAnUserInterfaceImp public function testLoginSuccess() { - $service = $this->getService(null, ['name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'lifetime' => 3600, 'always_remember_me' => true]); + $service = $this->getService(null, ['name' => 'foo', 'domain' => 'myfoodomain.foo', 'path' => '/foo/path', 'secure' => true, 'httponly' => true, 'samesite' => Cookie::SAMESITE_STRICT, 'lifetime' => 3600, 'always_remember_me' => true]); $request = new Request(); $response = new Response(); @@ -240,6 +241,7 @@ public function testLoginSuccess() $this->assertTrue($cookie->getExpiresTime() > time() + 3590 && $cookie->getExpiresTime() < time() + 3610); $this->assertEquals('myfoodomain.foo', $cookie->getDomain()); $this->assertEquals('/foo/path', $cookie->getPath()); + $this->assertSame(Cookie::SAMESITE_STRICT, $cookie->getSameSite()); } protected function getCookie($class, $username, $expires, $password)