Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

StormShadow's avatar

Session lifetime timeout and csrf token mismatch

Hi everyone,

I'm having an issue where if a user has a page displayed for longer than the session expiry (Laravel defaults to 2 hours lifetime in config/session), then this causes my forms to stop working because it throws token mismatch. How do you guys handle this?

0 likes
38 replies
StormShadow's avatar

@Snapey yes I saw that after I created my thread! Sorry about that. Hopefully we can get some discussion going as this issue stops my (AJAX submitted) forms cold! I wonder if it's a matter of just extending the session timeout lifetime and hope the user doesn't wait before they submit. Or I guess we could catch that error in jquery global ajax error handler and reload the page and have the user try again, as the reload would regenerate the session.

bashy's avatar

Keeping the token refreshed every X amount of minutes/hours is good. I've been thinking too and what about sending the new token back to the form with a

Redirect::back()->with('new_token', csrf_token());

Then pick it up (if set) in the form.

StormShadow's avatar

Hi @bashy thanks for replying. I'm curious about your token refresh idea. How would you do this? Also once you redirect I think the new session with new csrf token would automatically be available. It's the fact that the users form that they have been open for over two hours while they go get lunch has the old token that's why we're getting token mismatch.

bashy's avatar

Well, obviously the {!! Form::open() !!} adds it in auto but you could overwrite it with your own macro. Then do a @if to check if the new token is sent @else display original one.

Snapey's avatar

How about a javascript that disables all input elements 2 hours after the page loads, or replaces the form with a 'timeout' message?

bashy's avatar

^ That way there's no way to save the data already entered?

JacobBennett's avatar

I shared my solution over on the other thread for this that @Snapey started as well. Had this problem in a production app that was causing all sorts of mayhem. My solution was sort of like what you said @Snapey. I hate how banks pop-up this window letting you know your session is about to expire, but I had to resort to something similar.

@bashy are you suggesting an AJAX sort of heartbeat function to keep the session active over the 2 hour restriction? Say like every 30 minutes if a user is still on a form that hasn't been submitted, send an AJAX request over the line just to keep the token valid?

Linked other discussion https://laracasts.com/discuss/channels/general-discussion/crsf-checked-before-auth

bashy's avatar

Kind of (that was also another idea). Have JS update the token in the input.

garethdaine's avatar

Just had someone ask a similar question in IRC, does this work for you guys.

public function render($request, Exception $e)
{
    if ($e instanceof \Illuminate\Session\TokenMismatchException) {
        return redirect()->back()->withInput()->with('token', csrf_token());
    }

    return parent::render($request, $e);
}

Then check in your view for the new token and replace the old, as well as using Request::old() on your fields.

Not tested but I imagine it will get someone on the right track.

1 like
puzbie's avatar

I know this is an old question but isn't allowing a form to remain "active" for such a long time a bit of a security issue? I would have thought a javascript routine that disabled a form after a certain period of inactivity would be a better solution.

1 like
bashy's avatar

@puzbie Not if you redirect back with a new token while keeping the expire time the same?

puzbie's avatar

But say if somebody is logged into a site, and gets called away from their desk for whatever reason blah blah blah. Somebody else can come along and pretend to be them. Surely the better solution, on timeout, is to force them to log in again before processing the form?

bashy's avatar

@puzbie That's not what CSRF tokens are for. If you want session timeout to be shorter in your app, you can change that depending on how long you want it to be. That issue is the same for any site.

puzbie's avatar

I agree that its not what CSRF tokens are for. However, if you are getting this error it is because your form has been allowed to idle for 2 hours. If that is the case, my point was that it would be better to force a form refresh rather than just refresh the token.

bashy's avatar

@puzbie I don't see how refreshing the form would hide the information already entered? Or am I not on the same track? :P

Do you mean mean something like an auto-lockout? There's already packages for that and that's a very specific requirement.

Snapey's avatar

@puzbie suppose your application is an invoicing application. The user spends most of their time looking at a form to post a new invoice. They start to fill out the form and then go for their lunch. Their workstation may be locked at this time (normal desktop policy).

They return to their desk and finish the form, press submit and ... CRAP.. they see a login form.

Packages such as laravel-caffeine try to avoid this by keeping the session going, and making sure the csrf token does not expire.

A well-rounded application will look after the part-filled form by either auto-saving or returning the form data submitted prior to redirection.

1 like
puzbie's avatar

I'm not saying don't autosave, I'm saying re-authenticate. The two are not mutually exclusive. From a security standpoint, it is bad practice to not require re-authentication after a timeout. It doesn't have to be immediate. Amazon have a nice compromise. You can carry on surfing until you come to a critical point like checking out or altering your user details, at which point you will have to re-authenticate.

However, I get Bashy's point saying that this isn't what CSRF timeout is about. He's quite right. You shouldn't rely on it for your security. You should have a more robust system in place, which would make the issue of CSRF timeout moot.

1 like
shez1983's avatar

if you guys want to circumvent the csrf_token then why not just get rid of csrf_token? as you are effectively getting rid of the security this provides for you? - I dont think we should be doing that or maybe i have my wires crossed here.. and I also dont think this is a problem for majority of the people as they wont keep the forms open for long.. its an exceptional case. for which you could handle it by sending the user back to the form with a message if appropriate

puzbie's avatar

This is how I understand it:

The CSRF token is there to prevent cross-site-scripting. It is not there for any other form of security control. If you got rid of it, you would have no way of preventing CSRF, ie, you would have no way of knowing the true source of the HTTP request. If it didn't expire, somebody could open a form in their browser, look at the source code and lift that token onto their own form on their own site. Then, provided the original form wasn't submitted, they would be able to submit from the other site.

Even though the CSRF token times out, you shouldn't use it as your security measure to detect client inactivity. You should have a more robust measure in place, if security is an issue. The Amazon example I gave above is a good example of one, I think.

bashy's avatar

@puzbie I'm not sure I understand the part where you said about "someone could open a form in their browser... etc"? All tokens are different so they'd have to see your own token from your session.

puzbie's avatar

Well, what is the point of the token? I thought that it was to ensure that the session submitting the form is the same one that requested it.

As I said, that is how I understand it. Please don't assume that I understand it correctly. If my logic is incorrect then believe me I am all ears.

interludic's avatar

As people seem not to believe in a use case for the mentioned problems here is mine.

Use case: I have a webapp that uses laravel 5 and AngularJs. One area of it requires me to take an iPad with the page loaded away from connectivity for a day's work in the field. Using local browser storage in chrome, the device can be rebooted etc, without data loss. Now when i get back to the world of connectivity, i simply post the form to complete the task.

shangsunset's avatar

@puzbie I want to so re-authentication like you suggested after a form is open for too long and session expires. however, my login is an overlay and csrf_token() wont get refreshed. so when i login again, i still get tokenMismatchException. is there a way to handle this case? i dont want to lose the data user already has put in. thanks.

lafortuna18's avatar

You can set the session lifetime in the /app/config/session.php file, where 120 represents minutes.

/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/

'lifetime' => 120,

'expire_on_close' => false,
1 like
allenmccabe's avatar

Making an ajax request would either refresh the session, at which point the token is still valid, or start a new one. Checking the token for match before returning a new one won't work (as some have suggested in other forums). If you want the user to be able to leave a half completed form and return where they left off, the best thing I can think of is to display a blocking modal with a login form. This form would also need javascript to check for browser interaction and grab a new CSRF token (and replace in both the login form and the underlying) when the user comes back to the browser. If a successful login occurs, dismiss the modal.

On login screens in particular, a strategy like the one I outlined for the modal login form would also work, and I plan on testing an implementation today. Just grab a new token when the user moves the mouse or types on the keyboard.

Next

Please or to participate in this conversation.