Skip to content

Commit 2c846c6

Browse files
committed
Merge branch '2.7' into 2.8
* 2.7: clear CSRF tokens when the user is logged out
2 parents f75a193 + 682c866 commit 2c846c6

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\Logout;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
17+
use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
18+
19+
/**
20+
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
21+
*/
22+
class CsrfTokenClearingLogoutHandler implements LogoutHandlerInterface
23+
{
24+
private $csrfTokenStorage;
25+
26+
public function __construct(ClearableTokenStorageInterface $csrfTokenStorage)
27+
{
28+
$this->csrfTokenStorage = $csrfTokenStorage;
29+
}
30+
31+
public function logout(Request $request, Response $response, TokenInterface $token)
32+
{
33+
$this->csrfTokenStorage->clear();
34+
}
35+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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\Logout;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\HttpFoundation\Session\Session;
18+
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
19+
use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
20+
use Symfony\Component\Security\Http\Logout\CsrfTokenClearingLogoutHandler;
21+
22+
class CsrfTokenClearingLogoutHandlerTest extends TestCase
23+
{
24+
private $session;
25+
private $csrfTokenStorage;
26+
private $csrfTokenClearingLogoutHandler;
27+
28+
protected function setUp()
29+
{
30+
$this->session = new Session(new MockArraySessionStorage());
31+
$this->csrfTokenStorage = new SessionTokenStorage($this->session, 'foo');
32+
$this->csrfTokenStorage->setToken('foo', 'bar');
33+
$this->csrfTokenStorage->setToken('foobar', 'baz');
34+
$this->csrfTokenClearingLogoutHandler = new CsrfTokenClearingLogoutHandler($this->csrfTokenStorage);
35+
}
36+
37+
public function testCsrfTokenCookieWithSameNamespaceIsRemoved()
38+
{
39+
$this->assertSame('bar', $this->session->get('foo/foo'));
40+
$this->assertSame('baz', $this->session->get('foo/foobar'));
41+
42+
$this->csrfTokenClearingLogoutHandler->logout(new Request(), new Response(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
43+
44+
$this->assertFalse($this->csrfTokenStorage->hasToken('foo'));
45+
$this->assertFalse($this->csrfTokenStorage->hasToken('foobar'));
46+
47+
$this->assertFalse($this->session->has('foo/foo'));
48+
$this->assertFalse($this->session->has('foo/foobar'));
49+
}
50+
51+
public function testCsrfTokenCookieWithDifferentNamespaceIsNotRemoved()
52+
{
53+
$barNamespaceCsrfSessionStorage = new SessionTokenStorage($this->session, 'bar');
54+
$barNamespaceCsrfSessionStorage->setToken('foo', 'bar');
55+
$barNamespaceCsrfSessionStorage->setToken('foobar', 'baz');
56+
57+
$this->assertSame('bar', $this->session->get('foo/foo'));
58+
$this->assertSame('baz', $this->session->get('foo/foobar'));
59+
$this->assertSame('bar', $this->session->get('bar/foo'));
60+
$this->assertSame('baz', $this->session->get('bar/foobar'));
61+
62+
$this->csrfTokenClearingLogoutHandler->logout(new Request(), new Response(), $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
63+
64+
$this->assertTrue($barNamespaceCsrfSessionStorage->hasToken('foo'));
65+
$this->assertTrue($barNamespaceCsrfSessionStorage->hasToken('foobar'));
66+
$this->assertSame('bar', $barNamespaceCsrfSessionStorage->getToken('foo'));
67+
$this->assertSame('baz', $barNamespaceCsrfSessionStorage->getToken('foobar'));
68+
$this->assertFalse($this->csrfTokenStorage->hasToken('foo'));
69+
$this->assertFalse($this->csrfTokenStorage->hasToken('foobar'));
70+
71+
$this->assertFalse($this->session->has('foo/foo'));
72+
$this->assertFalse($this->session->has('foo/foobar'));
73+
$this->assertSame('bar', $this->session->get('bar/foo'));
74+
$this->assertSame('baz', $this->session->get('bar/foobar'));
75+
}
76+
}

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
},
2828
"require-dev": {
2929
"symfony/routing": "~2.2|~3.0.0",
30-
"symfony/security-csrf": "^2.8.31|^3.3.13",
30+
"symfony/security-csrf": "^2.8.41|^3.3.17",
3131
"psr/log": "~1.0"
3232
},
33+
"conflict": {
34+
"symfony/security-csrf": ">=2.8.0,<2.8.41 || >=3.0.0,<3.3.17 || >=3.4.0,<3.4.11"
35+
},
3336
"suggest": {
3437
"symfony/security-csrf": "For using tokens to protect authentication/logout attempts",
3538
"symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs"

0 commit comments

Comments
 (0)