20

If a user gets logged out (due to session expiration or for other reasons) in the background while using my Symfony2 application, I have implemented a JS layer appearing on the screen, allowing the user to log back in immediately and continue using the website.

The problem is, if the user is in the middle of filling a form and gets logged out, after logging back in using the JS layer, he's still looking at the same form with values he already managed to type in, but his session changes. The CSRF token in the form is therefore invalid.

Is there a way to generate a new CSRF token based on the current session and particular form, grab it by AJAX and replace in the form? Or maybe there is other solution to this?

I don't want to disable the CSRF protection.

grzechoo
  • 1,093
  • 3
  • 11
  • 20
  • 1
    I don't have enough reputation to comment place a comment on a solution, so I'll do it this way. The answer of thecatontheflat would probably work, but in my opinion that would break the whole concept of a CSRF protection: A bot can simply call the AJAX controller, fetch the token and use that to POST with the form. – vrijdenker Jul 15 '14 at 13:02

4 Answers4

33

Assuming that you use default CSRF Provider, in your AJAX controller you can get your CSRF Provider service and "ask" it to regenerate token:

Symfony 2.3 (and prior)

/** @var \Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider $csrf */
$csrf = $this->get('form.csrf_provider');
$token = $csrf->generateCsrfToken($intention); 

return new Response($token);

Symfony 2.4

/** @var \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface $csrf */
$csrf = $this->get('security.csrf.token_manager');
$token = $csrf->refreshToken($intention);

return new Response($token);
Vitalii Zurian
  • 17,858
  • 4
  • 64
  • 81
10

Use this to regenerate CSRF token (Since Symfony2.4):

$csrf = $this->get('security.csrf.token_manager'); //Symfony\Component\Security\Csrf\CsrfTokenManagerInterface
$token = $csrf->refreshToken($intention); // Intention is specified in form type

return new Response($token);
Bohdan Yurov
  • 365
  • 5
  • 9
4

Yes, the bot could fetch an csrf token and post something to the form, but as the token is bound to the session, it doesn't matter. CSRF tokens are not intended to prevent submission of forms by bots.

dgtl
  • 41
  • 1
1

To me the easier solution is to redirect user on the same form, passing data alredy inserted via POST.
In that way the token will be generated again in an automatic way.
Moreover, you'll not lost data input.

DonCallisto
  • 29,419
  • 9
  • 72
  • 100
  • Thanks, but I'm looking for a more general solution. I currently have a lot of custom validation functionalities, I would have to go through all of my forms one by one and adjust. Not easier at all. – grzechoo Jul 13 '12 at 09:30