Skip to content

Commit 5909d74

Browse files
[Security/Http] Remove CSRF tokens from storage on successful login
1 parent fa1827c commit 5909d74

File tree

6 files changed

+33
-7
lines changed

6 files changed

+33
-7
lines changed

src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363

6464
<service id="security.authentication.session_strategy" class="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy">
6565
<argument>%security.authentication.session_strategy.strategy%</argument>
66+
<argument type="service" id="security.csrf.token_storage" on-invalid="ignore" />
6667
</service>
6768
<service id="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface" alias="security.authentication.session_strategy" />
6869

src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ class CsrfFormLoginTest extends AbstractWebTestCase
1919
public function testFormLoginAndLogoutWithCsrfTokens($config)
2020
{
2121
$client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
22+
static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
2223

2324
$form = $client->request('GET', '/login')->selectButton('login')->form();
2425
$form['user_login[username]'] = 'johannes';
2526
$form['user_login[password]'] = 'test';
2627
$client->submit($form);
2728

29+
$this->assertFalse(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
30+
2831
$this->assertRedirect($client->getResponse(), '/profile');
2932

3033
$crawler = $client->followRedirect();
@@ -48,11 +51,14 @@ public function testFormLoginAndLogoutWithCsrfTokens($config)
4851
public function testFormLoginWithInvalidCsrfToken($config)
4952
{
5053
$client = $this->createClient(['test_case' => 'CsrfFormLogin', 'root_config' => $config]);
54+
static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
5155

5256
$form = $client->request('GET', '/login')->selectButton('login')->form();
5357
$form['user_login[_token]'] = '';
5458
$client->submit($form);
5559

60+
$this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
61+
5662
$this->assertRedirect($client->getResponse(), '/login');
5763

5864
$text = $client->followRedirect()->text(null, true);

src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@ public function testSessionLessRememberMeLogout()
3636
public function testCsrfTokensAreClearedOnLogout()
3737
{
3838
$client = $this->createClient(['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']);
39-
static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
4039

4140
$client->request('POST', '/login', [
4241
'_username' => 'johannes',
4342
'_password' => 'test',
4443
]);
4544

46-
$this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
47-
$this->assertSame('bar', static::$container->get('security.csrf.token_storage')->getToken('foo'));
45+
static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
4846

4947
$client->request('GET', '/logout');
5048

src/Symfony/Bundle/SecurityBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"symfony/security-core": "^4.4",
2626
"symfony/security-csrf": "^4.2|^5.0",
2727
"symfony/security-guard": "^4.2|^5.0",
28-
"symfony/security-http": "^4.4.5"
28+
"symfony/security-http": "^4.4.50"
2929
},
3030
"require-dev": {
3131
"doctrine/annotations": "^1.10.4",

src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\HttpFoundation\Request;
1515
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
16+
use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
1617

1718
/**
1819
* The default session strategy implementation.
@@ -31,10 +32,15 @@ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInte
3132
public const INVALIDATE = 'invalidate';
3233

3334
private $strategy;
35+
private $csrfTokenStorage = null;
3436

35-
public function __construct(string $strategy)
37+
public function __construct(string $strategy, ClearableTokenStorageInterface $csrfTokenStorage = null)
3638
{
3739
$this->strategy = $strategy;
40+
41+
if (self::MIGRATE === $strategy) {
42+
$this->csrfTokenStorage = $csrfTokenStorage;
43+
}
3844
}
3945

4046
/**
@@ -47,10 +53,12 @@ public function onAuthentication(Request $request, TokenInterface $token)
4753
return;
4854

4955
case self::MIGRATE:
50-
// Note: this logic is duplicated in several authentication listeners
51-
// until Symfony 5.0 due to a security fix with BC compat
5256
$request->getSession()->migrate(true);
5357

58+
if ($this->csrfTokenStorage) {
59+
$this->csrfTokenStorage->clear();
60+
}
61+
5462
return;
5563

5664
case self::INVALIDATE:

src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\HttpFoundation\Session\SessionInterface;
17+
use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface;
1718
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
1819
use Symfony\Component\Security\Http\Tests\Fixtures\TokenInterface;
1920

@@ -57,6 +58,18 @@ public function testSessionIsInvalidated()
5758
$strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class));
5859
}
5960

61+
public function testCsrfTokensAreCleared()
62+
{
63+
$session = $this->createMock(SessionInterface::class);
64+
$session->expects($this->once())->method('migrate')->with($this->equalTo(true));
65+
66+
$csrfStorage = $this->createMock(ClearableTokenStorageInterface::class);
67+
$csrfStorage->expects($this->once())->method('clear');
68+
69+
$strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE, $csrfStorage);
70+
$strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class));
71+
}
72+
6073
private function getRequest($session = null)
6174
{
6275
$request = $this->createMock(Request::class);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy