10000 Added automatically CSRF protected authenticators · symfony/symfony@60d396f · GitHub
[go: up one dir, main page]

Skip to content

Commit 60d396f

Browse files
committed
Added automatically CSRF protected authenticators
1 parent bf1a452 commit 60d396f

File tree

4 files changed

+99
-10
lines changed

4 files changed

+99
-10
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464
<argument type="abstract">stateless firewall keys</argument>
6565
</service>
6666

67+
<service id="security.listener.csrf_protection" class="Symfony\Component\Security\Http\EventListener\CsrfProtectionListener">
68+
<tag name="kernel.event_subscriber" />
69+
<argument type="service" id="security.csrf.token_manager" />
70+
</service>
71+
6772
<service id="security.listener.remember_me"
6873
class="Symfony\Component\Security\Http\EventListener\RememberMeListener"
6974
abstract="true">
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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\Authenticator;
13+
14+
/**
15+
* This interface can be implemented to automatically add CSF
16+
* protection to the authenticator.
17+
*
18+
* @author Wouter de Jong <wouter@wouterj.nl>
19+
*/
20+
interface CsrfProtectedAuthenticatorInterface
21+
{
22+
/**
23+
* An arbitrary string used to generate the value of the CSRF token.
24+
* Using a different string for each authenticator improves its security.
25+
*/
26+
public function getCsrfTokenId(): string;
27+
28+
/**
29+
* Returns the CSRF token contained in credentials if any.
30+
*
31+
* @param mixed $credentials the credentials returned by getCredentials()
32+
*/
33+
public function getCsrfToken($credentials): ?string;
34+
}

src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @final
3333
* @experimental in 5.1
3434
*/
35-
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator implements PasswordAuthenticatedInterface
35+
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator implements PasswordAuthenticatedInterface, CsrfProtectedAuthenticatorInterface
3636
{
3737
use TargetPathTrait;
3838

@@ -113,17 +113,15 @@ public function getUser($credentials): ?UserInterface
113113
return $this->userProvider->loadUserByUsername($credentials['username']);
114114
}
115115

116-
/* @todo How to do CSRF protection?
117-
public function checkCredentials($credentials, UserInterface $user): bool
116+
public function getCsrfTokenId(): string
118117
{
119-
if (null !== $this->csrfTokenManager) {
120-
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $credentials['csrf_token']))) {
121-
throw new InvalidCsrfTokenException('Invalid CSRF token.');
122-
}
123-
}
118+
return $this->options['csrf_token_id'];
119+
}
124120

125-
return $this->checkPassword($credentials, $user);
126-
}*/
121+
public function getCsrfToken($credentials): ?string
122+
{
123+
return $credentials['csrf_token'];
124+
}
127125

128126
public function createAuthenticatedToken(UserInterface $user, $providerKey): TokenInterface
129127
{
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/*
< 57AE /code>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\Core\Exception\InvalidCsrfTokenException;
16+
use Symfony\Component\Security\Csrf\CsrfToken;
17+
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
18+
use Symfony\Component\Security\Http\Authenticator\CsrfProtectedAuthenticatorInterface;
19+
use Symfony\Component\Security\Http\Event\VerifyAuthenticatorCredentialsEvent;
20+
21+
class CsrfProtectionListener implements EventSubscriberInterface
22+
{
23+
private $csrfTokenManager;
24+
25+
public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
26+
{
27+
$this->csrfTokenManager = $csrfTokenManager;
28+
}
29+
30+
public function verifyCredentials(VerifyAuthenticatorCredentialsEvent $event): void
31+
{
32+
$authenticator = $event->getAuthenticator();
33+
if (!$authenticator instanceof CsrfProtectedAuthenticatorInterface) {
34+
return;
35+
}
36+
37+
$csrfTokenValue = $authenticator->getCsrfToken($event->getCredentials());
38+
if (null === $csrfTokenValue) {
39+
return;
40+
}
41+
42+
$csrfToken = new CsrfToken($authenticator->getCsrfTokenId(), $csrfTokenValue);
43+
if (false === $this->csrfTokenManager->isTokenValid($csrfToken)) {
44+
throw new InvalidCsrfTokenException('Invalid CSRF token.');
45+
}
46+
}
47+
48+
public static function getSubscribedEvents(): array
49+
{
50+
return [VerifyAuthenticatorCredentialsEvent::class => ['verifyCredentials', 256]];
51+
}
52+
}

0 commit comments

Comments
 (0)
0