Skip to content

[HttpFoundation] Fix clearing CHIPS cookies #53703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions .github/expected-missing-return-types.diff
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExt
+ protected function registerMappingDrivers(array $objectManager, ContainerBuilder $container): void
{
// configure metadata driver for each bundle based on the type of mapping files found
@@ -238,5 +238,5 @@ abstract class AbstractDoctrineExtension extends Extension
@@ -240,5 +240,5 @@ abstract class AbstractDoctrineExtension extends Extension
* @throws \InvalidArgumentException
*/
- protected function assertValidMappingConfiguration(array $mappingConfig, string $objectManagerName)
+ protected function assertValidMappingConfiguration(array $mappingConfig, string $objectManagerName): void
{
if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) {
@@ -328,5 +328,5 @@ abstract class AbstractDoctrineExtension extends Extension
@@ -330,5 +330,5 @@ abstract class AbstractDoctrineExtension extends Extension
* @throws \InvalidArgumentException in case of unknown driver type
*/
- protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, string $cacheName)
Expand Down Expand Up @@ -1942,8 +1942,8 @@ diff --git a/src/Symfony/Component/Config/Exception/LoaderLoadException.php b/sr
diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Component/Config/FileLocator.php
--- a/src/Symfony/Component/Config/FileLocator.php
+++ b/src/Symfony/Component/Config/FileLocator.php
@@ -34,5 +34,5 @@ class FileLocator implements FileLocatorInterface
* @return string|array
@@ -36,5 +36,5 @@ class FileLocator implements FileLocatorInterface
* @psalm-return ($first is true ? string : string[])
*/
- public function locate(string $name, ?string $currentPath = null, bool $first = true)
+ public function locate(string $name, ?string $currentPath = null, bool $first = true): string|array
Expand All @@ -1952,8 +1952,8 @@ diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Componen
diff --git a/src/Symfony/Component/Config/FileLocatorInterface.php b/src/Symfony/Component/Config/FileLocatorInterface.php
--- a/src/Symfony/Component/Config/FileLocatorInterface.php
+++ b/src/Symfony/Component/Config/FileLocatorInterface.php
@@ -31,4 +31,4 @@ interface FileLocatorInterface
* @throws FileLocatorFileNotFoundException If a file is not found
@@ -33,4 +33,4 @@ interface FileLocatorInterface
* @psalm-return ($first is true ? string : string[])
*/
- public function locate(string $name, ?string $currentPath = null, bool $first = true);
+ public function locate(string $name, ?string $currentPath = null, bool $first = true): string|array;
Expand Down Expand Up @@ -3776,7 +3776,7 @@ diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByAc
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
@@ -38,5 +38,5 @@ class ResolveBindingsPass extends AbstractRecursivePass
@@ -39,5 +39,5 @@ class ResolveBindingsPass extends AbstractRecursivePass
* @return void
*/
- public function process(ContainerBuilder $container)
Expand Down Expand Up @@ -4088,7 +4088,7 @@ diff --git a/src/Symfony/Component/DependencyInjection/ContainerInterface.php b/
diff --git a/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php b/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php
--- a/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php
+++ b/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php
@@ -71,5 +71,5 @@ class AutowiringFailedException extends RuntimeException
@@ -69,5 +69,5 @@ class AutowiringFailedException extends RuntimeException
* @return string
*/
- public function getServiceId()
Expand Down Expand Up @@ -7449,14 +7449,14 @@ diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Sy
+ public function removeCookie(string $name, ?string $path = '/', ?string $domain = null): void
{
$path ??= '/';
@@ -237,5 +237,5 @@ class ResponseHeaderBag extends HeaderBag
@@ -239,5 +239,5 @@ class ResponseHeaderBag extends HeaderBag
* @return void
*/
- public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null)
+ public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null): void
- public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null /* , bool $partitioned = false */)
+ public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null /* , bool $partitioned = false */): void
{
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite));
@@ -247,5 +247,5 @@ class ResponseHeaderBag extends HeaderBag
$partitioned = 6 < \func_num_args() ? \func_get_arg(6) : false;
@@ -251,5 +251,5 @@ class ResponseHeaderBag extends HeaderBag
* @return string
*/
- public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto
->scalarNode('domain')->defaultNull()->end()
->scalarNode('secure')->defaultFalse()->end()
->scalarNode('samesite')->defaultNull()->end()
->scalarNode('partitioned')->defaultFalse()->end()
->end()
->end()
->end()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,39 @@ public function testLogoutCsrf()
}
}

public function testLogoutDeleteCookies()
{
$config = [
'firewalls' => [
'stub' => [
'logout' => [
'delete_cookies' => [
'my_cookie' => [
'path' => '/',
'domain' => 'example.org',
'secure' => true,
'samesite' => 'none',
'partitioned' => true,
],
],
],
],
],
];
$config = array_merge(static::$minimalConfig, $config);

$processor = new Processor();
$configuration = new MainConfiguration([], []);
$processedConfig = $processor->processConfiguration($configuration, [$config]);
$this->assertArrayHasKey('delete_cookies', $processedConfig['firewalls']['stub']['logout']);
$deleteCookies = $processedConfig['firewalls']['stub']['logout']['delete_cookies'];
$this->assertSame('/', $deleteCookies['my_cookie']['path']);
$this->assertSame('example.org', $deleteCookies['my_cookie']['domain']);
$this->assertTrue($deleteCookies['my_cookie']['secure']);
$this->assertSame('none', $deleteCookies['my_cookie']['samesite']);
$this->assertTrue($deleteCookies['my_cookie']['partitioned']);
}

public function testDefaultUserCheckers()
{
$processor = new Processor();
Expand Down
8 changes: 6 additions & 2 deletions src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,15 @@ public function getCookies(string $format = self::COOKIES_FLAT): array
/**
* Clears a cookie in the browser.
*
* @param bool $partitioned
*
* @return void
*/
public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null)
public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null /* , bool $partitioned = false */)
{
$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite));
$partitioned = 6 < \func_num_args() ? \func_get_arg(6) : false;

$this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite, $partitioned));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ public function testClearCookieSamesite()
$this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d M Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure; samesite=none', $bag);
}

public function testClearCookiePartitioned()
{
$bag = new ResponseHeaderBag([]);

$bag->clearCookie('foo', '/', null, true, false, 'none', true);
$this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d M Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure; samesite=none; partitioned', $bag);
}

public function testReplace()
{
$bag = new ResponseHeaderBag([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function onLogout(LogoutEvent $event): void
}

foreach ($this->cookies as $cookieName => $cookieData) {
$response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], $cookieData['secure'] ?? false, true, $cookieData['samesite'] ?? null);
$response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], $cookieData['secure'] ?? false, true, $cookieData['samesite'] ?? null, $cookieData['partitioned'] ?? false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function testLogout()
$event = new LogoutEvent(new Request(), null);
$event->setResponse($response);

$listener = new CookieClearingLogoutListener(['foo' => ['path' => '/foo', 'domain' => 'foo.foo', 'secure' => true, 'samesite' => Cookie::SAMESITE_STRICT], 'foo2' => ['path' => null, 'domain' => null]]);
$listener = new CookieClearingLogoutListener(['foo' => ['path' => '/foo', 'domain' => 'foo.foo', 'secure' => true, 'samesite' => Cookie::SAMESITE_STRICT, 'partitioned' => true], 'foo2' => ['path' => null, 'domain' => null]]);

$cookies = $response->headers->getCookies();
$this->assertCount(0, $cookies);
Expand All @@ -43,6 +43,7 @@ public function testLogout()
$this->assertEquals('foo.foo', $cookie->getDomain());
$this->assertEquals(Cookie::SAMESITE_STRICT, $cookie->getSameSite());
$this->assertTrue($cookie->isSecure());
$this->assertTrue($cookie->isPartitioned());
$this->assertTrue($cookie->isCleared());

$cookie = $cookies['']['/']['foo2'];
Expand All @@ -51,6 +52,7 @@ public function testLogout()
$this->assertNull($cookie->getDomain());
$this->assertNull($cookie->getSameSite());
$this->assertFalse($cookie->isSecure());
$this->assertFalse($cookie->isPartitioned());
$this->assertTrue($cookie->isCleared());
}
}