Added automatically CSRF protected authenticators
This commit is contained in:
parent
bf1a452e94
commit
60d396f2d1
@ -64,6 +64,11 @@
|
||||
<argument type="abstract">stateless firewall keys</argument>
|
||||
</service>
|
||||
|
||||
<service id="security.listener.csrf_protection" class="Symfony\Component\Security\Http\EventListener\CsrfProtectionListener">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
<argument type="service" id="security.csrf.token_manager" />
|
||||
</service>
|
||||
|
||||
<service id="security.listener.remember_me"
|
||||
class="Symfony\Component\Security\Http\EventListener\RememberMeListener"
|
||||
abstract="true">
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\Authenticator;
|
||||
|
||||
/**
|
||||
* This interface can be implemented to automatically add CSF
|
||||
* protection to the authenticator.
|
||||
*
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
*/
|
||||
interface CsrfProtectedAuthenticatorInterface
|
||||
{
|
||||
/**
|
||||
* An arbitrary string used to generate the value of the CSRF token.
|
||||
* Using a different string for each authenticator improves its security.
|
||||
*/
|
||||
public function getCsrfTokenId(): string;
|
||||
|
||||
/**
|
||||
* Returns the CSRF token contained in credentials if any.
|
||||
*
|
||||
* @param mixed $credentials the credentials returned by getCredentials()
|
||||
*/
|
||||
public function getCsrfToken($credentials): ?string;
|
||||
}
|
@ -32,7 +32,7 @@ use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||
* @final
|
||||
* @experimental in 5.1
|
||||
*/
|
||||
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator implements PasswordAuthenticatedInterface
|
||||
class FormLoginAuthenticator extends AbstractLoginFormAuthenticator implements PasswordAuthenticatedInterface, CsrfProtectedAuthenticatorInterface
|
||||
{
|
||||
use TargetPathTrait;
|
||||
|
||||
@ -113,17 +113,15 @@ class FormLoginAuthenticator extends AbstractLoginFormAuthenticator implements P
|
||||
return $this->userProvider->loadUserByUsername($credentials['username']);
|
||||
}
|
||||
|
||||
/* @todo How to do CSRF protection?
|
||||
public function checkCredentials($credentials, UserInterface $user): bool
|
||||
public function getCsrfTokenId(): string
|
||||
{
|
||||
if (null !== $this->csrfTokenManager) {
|
||||
if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $credentials['csrf_token']))) {
|
||||
throw new InvalidCsrfTokenException('Invalid CSRF token.');
|
||||
}
|
||||
}
|
||||
return $this->options['csrf_token_id'];
|
||||
}
|
||||
|
||||
return $this->checkPassword($credentials, $user);
|
||||
}*/
|
||||
public function getCsrfToken($credentials): ?string
|
||||
{
|
||||
return $credentials['csrf_token'];
|
||||
}
|
||||
|
||||
public function createAuthenticatedToken(UserInterface $user, $providerKey): TokenInterface
|
||||
{
|
||||
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Security\Http\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Authenticator\CsrfProtectedAuthenticatorInterface;
|
||||
use Symfony\Component\Security\Http\Event\VerifyAuthenticatorCredentialsEvent;
|
||||
|
||||
class CsrfProtectionListener implements EventSubscriberInterface
|
||||
{
|
||||
private $csrfTokenManager;
|
||||
|
||||
public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
|
||||
{
|
||||
$this->csrfTokenManager = $csrfTokenManager;
|
||||
}
|
||||
|
||||
public function verifyCredentials(VerifyAuthenticatorCredentialsEvent $event): void
|
||||
{
|
||||
$authenticator = $event->getAuthenticator();
|
||||
if (!$authenticator instanceof CsrfProtectedAuthenticatorInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
$csrfTokenValue = $authenticator->getCsrfToken($event->getCredentials());
|
||||
if (null === $csrfTokenValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
$csrfToken = new CsrfToken($authenticator->getCsrfTokenId(), $csrfTokenValue);
|
||||
if (false === $this->csrfTokenManager->isTokenValid($csrfToken)) {
|
||||
throw new InvalidCsrfTokenException('Invalid CSRF token.');
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [VerifyAuthenticatorCredentialsEvent::class => ['verifyCredentials', 256]];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user