[Security] Added check_post_only to the login link authenticator

This commit is contained in:
Wouter de Jong 2020-10-13 16:21:35 +02:00 committed by Fabien Potencier
parent 01b064d97a
commit 5093e0df06
4 changed files with 28 additions and 4 deletions

View File

@ -36,7 +36,11 @@ class LoginLinkFactory extends AbstractFactory implements AuthenticatorFactoryIn
$builder
->scalarNode('check_route')
->isRequired()
->info('Route that will validate the login link - e.g. app_login_link_verify.')
->info('Route that will validate the login link - e.g. "app_login_link_verify".')
->end()
->scalarNode('check_post_only')
->defaultFalse()
->info('If true, only HTTP POST requests to "check_route" will be handled by the authenticator.')
->end()
->arrayNode('signature_properties')
->isRequired()
@ -128,6 +132,7 @@ class LoginLinkFactory extends AbstractFactory implements AuthenticatorFactoryIn
->replaceArgument(3, new Reference($this->createAuthenticationFailureHandler($container, $firewallName, $config)))
->replaceArgument(4, [
'check_route' => $config['check_route'],
'check_post_only' => $config['check_post_only'],
]);
return $authenticatorId;

View File

@ -13,6 +13,7 @@ CHANGELOG
* Added translator to `\Symfony\Component\Security\Http\Authenticator\JsonLoginAuthenticator` and `\Symfony\Component\Security\Http\Firewall\UsernamePasswordJsonAuthenticationListener` to translate authentication failure messages
* Added a CurrentUser attribute to force the UserValueResolver to resolve an argument to the current user.
* Added `LoginThrottlingListener`.
* Added `LoginLinkAuthenticator`.
5.1.0
-----

View File

@ -43,18 +43,18 @@ final class LoginLinkAuthenticator extends AbstractAuthenticator implements Inte
$this->httpUtils = $httpUtils;
$this->successHandler = $successHandler;
$this->failureHandler = $failureHandler;
$this->options = $options;
$this->options = $options + ['check_post_only' => false];
}
public function supports(Request $request): ?bool
{
return $this->httpUtils->checkRequestPath($request, $this->options['check_route']);
return ($this->options['check_post_only'] ? $request->isMethod('POST') : true)
&& $this->httpUtils->checkRequestPath($request, $this->options['check_route']);
}
public function authenticate(Request $request): PassportInterface
{
$username = $request->get('user');
if (!$username) {
throw new InvalidLoginLinkAuthenticationException('Missing user from link.');
}

View File

@ -39,6 +39,24 @@ class LoginLinkAuthenticatorTest extends TestCase
$this->failureHandler = $this->createMock(AuthenticationFailureHandlerInterface::class);
}
/**
* @dataProvider provideSupportData
*/
public function testSupport(array $options, $request, bool $supported)
{
$this->setUpAuthenticator($options);
$this->assertEquals($supported, $this->authenticator->supports($request));
}
public function provideSupportData()
{
yield [['check_route' => '/validate_link'], Request::create('/validate_link?hash=abc123'), true];
yield [['check_route' => '/validate_link'], Request::create('/login?hash=abc123'), false];
yield [['check_route' => '/validate_link', 'check_post_only' => true], Request::create('/validate_link?hash=abc123'), false];
yield [['check_route' => '/validate_link', 'check_post_only' => true], Request::create('/validate_link?hash=abc123', 'POST'), true];
}
public function testSuccessfulAuthenticate()
{
$this->setUpAuthenticator();