How to handle an expired CSRF token after a page is left open

I’m using CodeIgniter 2 along with the Ion Auth authorization system by Ben Edmunds.

After creating my project, I would sometimes get a CodeIgniter error upon certain login attempts but this error was intermittent.

The action you have requested is not allowed.

After some troubleshooting, it became apparent this error was caused by an invalid CSRF token. Why is the token invalid? Well, in CodeIgniter’s configuration file, it’s set to expire in 4 hours. So if you load your login page and allow it to sit there for 4 hours before attempting a login, the CSRF tokens will expire and this will generate the error message as above. Simply reloading the login page avoids any issues.

You can verify this error message for yourself by deleting the CSRF cookie after you load the login page.

A cleaner solution would be to redirect to a custom error page or to display a flash message. However, this solution is not as simple as it sounds because when you extend the CodeIgniter Security class, certain hook-points are not available and you cannot yet access CodeIgniter’s Super Object using get_instance().

So when you extend the Security class, you’re limited to standard PHP. In this case, I’m using PHP header() to redirect the offending login page (or any form page) back to itself.

This works fine except that the user gets a screen refresh without any indication why they have to enter their login credentials a seconds time.

I decided to make this a bit more user-friendly by adding another function into a Controller, in my case, the Ion Auth controller…

As you can see, this function sets a flash message telling the user what happened and then redirects them to a fresh instance of the login page.

Session cookie automatically reset due to expired browser session. Please try again.

Instead of using PHP header() to redirect a page refresh, redirect to this new Ion Auth controller function at /auth/csrf_redirect.

The minor downside to this method is that you are always redirected back to the login page rather than a refresh of whatever page/form you’re trying to submit. However, that should be a moot point, since the session cookie expires at nearly the same time as the CSRF cookie, you’d be redirected back to the same login page regardless. You may also not be requiring the user be logged in for your particular form, so please be aware and re-direct accordingly.

8 Replies to “How to handle an expired CSRF token after a page is left open”

  1. Your code has a flaw: you must exit or die after a redirect header is called, otherwise the rest of the code will still be executed.

    1. It’s unclear which bit of code you’re asking about. Although, if you’re asking about extending classes, I refer you to the CodeIgniter documentation on that topic.

    2. First check in application/config/config.php for $config['subclass_prefix']. See what it’s set to, it should be MY_ by default.

      Create a file called MY_Security.php in your application/core folder.
      Put in the top of it like the rest of CI files.

      Now paste the code from this tutorial below and save.

  2. Be aware that the session might not have expired. So user could still be logged into the system, on a page with a form. So when posting that form, they would need to be redirected to the current page with an error message. Either way not a very user-friendly approach. Reloading CSRF would be better as the user doesn’t notice

  3. This is cool. I’ve been trying to figure this out on my own, but to no avail. By the way is this CSRF trick applicable for Codeigniter 3+? Thanks a ton!

Leave a Reply

Your email address will not be published. Required fields are marked *