I'm implementing CSRF protection (using Symfony's CSRF library), and I'm wondering what response to send to clients upon receiving an invalid token.

Currently we have a session that lasts 30 days, and we'd like the CSRF token to expire after 12 hours (I'm keeping track of the expire time in the backend, not a cookie). So there is a possibility that a user may leave a page open all day and try to submit a form.

I've seen this happen with JIRA when I return to my computer a day after leaving a page open, as their session is long lasting as well, but the CSRF token only lasts a day or so. My plan right now is similar to that flow — to send a 403 error, and then a new token will be sent on the next GET request (assuming their session is still valid).

Also, what is the recommendation for data the user filled out in HTML forms? Should I keep track of it and repopulate the form with data they already entered when they finally get back to that page?

  • What kind of CSRF mechanism are you using? (Im not familiar with Symfony.) Is it a synchronizer token or a double submit cookie?
    – Anders
    Mar 22, 2018 at 18:11
  • Also, are you working against an API, or are you posting forms the old fashioned way?
    – Anders
    Mar 22, 2018 at 18:12
  • It's left up to the implementer how to send and receive the token. I am supporting both forms and API (if the API request includes an auth token I'm not checking for CSRF though).So I'm sending it as a cookie, and expect it back in a header when the API is used. For forms I'm setting it as a hidden input, and then expect it back as part of the submission. Mar 22, 2018 at 19:37

2 Answers 2


I take it that this is for the "synchronizer token" pattern, and not "double submit cookie", since tokens don't really expire in the latter case.

You can mitigate the problem by making your CSRF-tokens more long lived. Only have one token per session (as opposed to per form), and make it as long lived as the session. So if the CSRF-token has expired, so has the session. And then the request should be rejected anyway.

That said, if for some reason you get a request with a valid session but an invalid CSRF-token, what should you do? As you say, status 403 is a good choise. For an API, you could respond with some kind of error object or message explaining to the client what went wrong. Or just an empty body, if that is how you deal with errors.

For classical form submissions, it's a bit trickier. If you want to play really nice, you should respond with the form in the same state as the user tried to submit it, plus an error message. This is a bit of a hazzle to implement, but perhaps you have a similar system in place already for other errors.

Note that you can return the new token (as a cookie, or form field, or whatever) already in the reply to the first request with the expired token. No need to make the client make another request just to get it.

  • Thanks for the response! I have a follow up. Do you think it's appropriate to send a new token back in the case that the client submitted an invalid token? Not just an expired token, but either no token at all or a completely invalid one. Mar 23, 2018 at 14:30
  • @JonathanFrankel I see no problem with that. In fact, an expired token might appear to be invalid, if the server no longer stores it.
    – Anders
    Mar 23, 2018 at 14:33

In the balance one tries to strike between security and usability, there are a lot of contextual details that weigh strongly or weakly in one direction or another-

  • what are the risks from a forged request, and related benefits to an attacker?
  • how plausible is a CSRF for your user base; relatedly, what other defenses are in place (e.g. frame busting, forced TLS, CSP, etc) against similar kinds of attacks that the site and users are likely to face?
  • how painful is it to users to be subjected to token renewal or form resubmission machinery?

Etc. So it really depends.

In general, a 30 day session and 12 hour token are much more strongly weighed in the direction of usability. So- you should confirm that's appropriate for your context.

Assuming it is, in a usability-oriented context, having any workflow or error condition that requires users to do something a second time is going to be suboptimal. So adopting a solution that preserves user inputs in all cases if the token expires, or informs the user that the token is on the verge of expiring and should be renewed, or any of many other options, is probably a good idea.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .