CaptchaBundle icon indicating copy to clipboard operation
CaptchaBundle copied to clipboard

Captcha is not validated in Symfony 5.0.8 login form

Open markuskuerten opened this issue 5 years ago • 4 comments

In my Symfony 5.0.8 application, the "validate" method is not called in the "CaptchaValidator" class after sending the login form.

I have integrated the captcha (v2.1.3) as described in the instructions, but it just does not work in my login form.

Could it be that special settings are required for a Symfony login form that are not described in the documentation?

During my research on the Internet I came across the following older post, which describes exactly the same problem that I have now, but with Symfony 2

https://github.com/Gregwar/CaptchaBundle/issues/99

It would be great if I could be given a tip on how to get the captcha up and running in my login form.

Or is it still not possible to use the gregwar captcha in a Symfony login form?

If you need more information or code examples please let me know.

Kind regards

markuskuerten avatar May 27 '20 20:05 markuskuerten

@markuskuerten could you provide a little more information? I also use Symfony 5.0.8 and have not made any adjustments to get it working. For example, do you have the same login form as Symfony explains in their documentation? https://symfony.com/doc/current/security/form_login_setup.html

Olaf1989 avatar Jun 05 '20 13:06 Olaf1989

Hello Olaf,

I am happy to give you more information.

I have created a login form as described in the Symfony documentation (https://symfony.com/doc/current/security/form_login_setup.html).

For the form I have created my own Form Type class (src/Form/UserType.php).

The captcha is shown to me in my login form.

I can see that the event listener is added.

File: vendor/gregwar/captcha-bundle/Type/CaptchaType.php Line: 68

$builder->addEventListener(FormEvents::POST_SUBMIT, array($validator, 'validate'));

However, the "validate" method in the "vendor/gregwar/captcha-bundle/Validator/CaptchaValidator.php" class is not executed after the login form has been sent.

It looks like the event listener is not running after the login form has been sent.

I am attaching my files to this comment.

symfony.local.zip

It would be great if you could give me a tip on what I'm doing wrong here.

markuskuerten avatar Jun 07 '20 12:06 markuskuerten

@markuskuerten thanks for the supplied source code. I briefly looked at what could be the possible cause. I think this is mainly due to the fact that the Symfony login process does not actually submit a form, but it is caught early on. Because I tested some things quickly and also could not capture the data with PRE_SUBMIT event. POST_SET_DATA event works, however it is already executed during the generation of the form (this confirms that the event listener is at least registered and executed).

It seems that you will have to add your own event listener in which you listen to the kernel requests and still call the Captcha validation. See an example of how this could be done here: https://stackoverflow.com/questions/46275065/symfony-pre-login-event-listener/46275931#answer-46275931

@Gregwar (or someone else) maybe you know a little more about this or a better solution?

URLs for reference: https://symfony.com/doc/current/form/events.html

Olaf1989 avatar Jun 10 '20 20:06 Olaf1989

It's work :

Security\LoginFormAuthenticator

public function getCredentials(Request $request)
{
        $credentials = [
	        'username' => $request->request->get('username'),
	        'password' => $request->request->get('password'),
	        'csrf_token' => $request->request->get('_csrf_token'),
	        'captcha' => $request->request->get('captcha'),
	        'phrase' => $request->getSession()->get('phrase')
        ];
        $request->getSession()->set(
	        Security::LAST_USERNAME,
	        $credentials['username']
        );
        
        return $credentials;
}
	
public function getUser($credentials, UserProviderInterface $userProvider)
{
        $token = new CsrfToken('authenticate', $credentials['csrf_token']);
        if (!$this->csrfTokenManager->isTokenValid($token)) {
	        throw new InvalidCsrfTokenException();
        }
        
        if ($credentials['phrase'] != $credentials['captcha']) {
	        throw new CustomUserMessageAuthenticationException('Wrong captcha !');
        }
        
        $user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $credentials['username']]);
        
        if (!$user) {
	        throw new CustomUserMessageAuthenticationException('Email could not be found.');
        }
        
        return $user;
}

ghost avatar Apr 05 '21 16:04 ghost