Skip to content

Commit 296d05c

Browse files
committed
feature #49306 [Security] Add logout configuration for Clear-Site-Data header (maxbeckers)
This PR was merged into the 6.3 branch. Discussion ---------- [Security] Add logout configuration for Clear-Site-Data header | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #49266 | License | MIT | Doc PR | symfony/symfony-docs#17900 Enhance security by issuing a Clear-Site-Data header on logout. * [Clear-Site-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data#sign_out_of_a_web_site) Documentation * Example: https://www.w3.org/TR/clear-site-data/#example-signout Default config is off. Config example for all: ```yaml security: # ... firewalls: main: # ... logout: path: app_logout clear_site_data: - "*" ``` Instead of all with the ``*`` it's also possible to add a set of ``cache``, ``cookies``, ``storage``, ``executionContexts``. For example without cookies it will look like this: ```yaml security: # ... firewalls: main: # ... logout: path: app_logout clear_site_data: - cache - storage - executionContexts ``` **TODO** - [x] Doc PR symfony/symfony-docs#17900 Commits ------- f9e76c1e47 [Security] Add logout configuration for Clear-Site-Data header
2 parents cdf9dc4 + 987c769 commit 296d05c

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Http\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\Security\Http\Event\LogoutEvent;
16+
17+
/**
18+
* Handler for Clear-Site-Data header during logout.
19+
*
20+
* @author Max Beckers <beckers.maximilian@gmail.com>
21+
*
22+
* @final
23+
*/
24+
class ClearSiteDataLogoutListener implements EventSubscriberInterface
25+
{
26+
private const HEADER_NAME = 'Clear-Site-Data';
27+
28+
/**
29+
* @param string[] $cookieValue The value for the Clear-Site-Data header.
30+
* Can be '*' or a subset of 'cache', 'cookies', 'storage', 'executionContexts'.
31+
*/
32+
public function __construct(private readonly array $cookieValue)
33+
{
34+
}
35+
36+
public function onLogout(LogoutEvent $event): void
37+
{
38+
if (!$event->getResponse()?->headers->has(static::HEADER_NAME)) {
39+
$event->getResponse()->headers->set(static::HEADER_NAME, implode(', ', array_map(fn ($v) => '"'.$v.'"', $this->cookieValue)));
40+
}
41+
}
42+
43+
public static function getSubscribedEvents(): array
44+
{
45+
return [
46+
LogoutEvent::class => 'onLogout',
47+
];
48+
}
49+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Http\Tests\EventListener;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\Security\Http\Event\LogoutEvent;
18+
use Symfony\Component\Security\Http\EventListener\ClearSiteDataLogoutListener;
19+
20+
class ClearSiteDataLogoutListenerTest extends TestCase
21+
{
22+
/**
23+
* @dataProvider provideClearSiteDataConfig
24+
*/
25+
public function testLogout(array $clearSiteDataConfig, string $expectedHeader)
26+
{
27+
$response = new Response();
28+
$event = new LogoutEvent(new Request(), null);
29+
$event->setResponse($response);
30+
31+
$listener = new ClearSiteDataLogoutListener($clearSiteDataConfig);
32+
33+
$headerCountBefore = $response->headers->count();
34+
35+
$listener->onLogout($event);
36+
37+
$this->assertEquals(++$headerCountBefore, $response->headers->count());
38+
39+
$this->assertNotNull($response->headers->get('Clear-Site-Data'));
40+
$this->assertEquals($expectedHeader, $response->headers->get('Clear-Site-Data'));
41+
}
42+
43+
public static function provideClearSiteDataConfig(): iterable
44+
{
45+
yield [['*'], '"*"'];
46+
yield [['cache', 'cookies', 'storage', 'executionContexts'], '"cache", "cookies", "storage", "executionContexts"'];
47+
}
48+
}

0 commit comments

Comments
 (0)