cbj4074's avatar

Laracasts forum does not handle CSRF token expiry gracefully; login fails silently

Suppose that I'm visiting the laracasts.com website and I leave it open after reading an article. The next day, I come back to the computer and decide I'd like to login and participate in the thread I'm viewing.

When I click Login, and enter my credentials, the login form submission fails silently, with no visual feedback to the user whatsoever.

I had to open the browser's DevTools console to see that the underlying cause is an expired CSRF token.

I find this puzzling, especially on an otherwise well-built website, presumably built and maintained by Laravel experts. :)

For what it's worth, I would avoid using something like https://github.com/GeneaLabs/laravel-caffeine because it will keep a tremendous number of sessions alive for no good reason.

While it may be tempting to say "Your token has expired, please refresh the page", it would be a lot more elegant to modify the JS that processes the authentication response such that if the token is expired, a new one is requested and used in a subsequent request that is sent automatically, and completely transparently where the user is concerned.

This has been a problem for quite some time (maybe since launch); it would be nice to see it fixed.

0 likes
11 replies
jlrdw's avatar

Why don't you just get in the habit of always closing your browser if you leave the computer. Logging into laravel does not take that long.

cbj4074's avatar

@jlrdw This is a usability problem; the fact that I hit "Login" and "nothing happens" is inexcusable, in my opinion. Whatever actions I may or may not have taken on the site prior to attempting to login are irrelevant. Whether or not login functions correctly should not be contingent upon my browsing habits and for how long my browser has been open during any given session.

If you had built this website for a client, and the client told you, "Hey, people are trying to login and when they click the Login button, nothing happens," would you tell your client, "Oh, yeah, don't worry about that, just tell people to close their browsers every time they finish using their computers and this won't happen." I hope not.

@somnathsah That advice is sound, in general, but using redirect()->back()->withInput() in this instance would be inappropriate, and provide a poor user experience, because the login form is presented in a modal dialog. A proper fix for this issue must utilize AJAX.

somnathsah's avatar

Yes @jirdw this is about the forum :-), but in case someone want to handle this error.

somnathsah's avatar

@cbj4074 we can implement a JS code which will logout from the site after the session time gets expired, redirect to login page and replace the login page with button something like "login again" which will refresh the CSRF token.

Cronix's avatar

I agree it's not a good solution. It's bugged me for awhile (laravel in general, not this site specifically).

Even if not using ajax... if you have a form that submits to a different url (like you should), and you let that form sit there until the token expires and then try to submit the form, you get the message that the page is expired and to refresh the page. However, in that situation, if you refresh the page, it resends the form with the expired token again and the user is stuck there in a loop with no idea of why it's not working. They are doing what the message said and refreshing the page. Remember, we're on the url that the form submits to, which isn't a page, it's accepting a POST (etc) request.

They (regular users) don't know about sessions or anything, nor should they. It's a very poor ux problem. @jlrdw It's not enough to tell users they should be logging out every time. That's not realistic. Government/sensitive job? Hell yes. A site for the public? No.

@somnathsah That's a pretty good solution, but as @cbj4074 mentioned it won't work for all situations. I guess it should check if the request was ajax and return a 422 response with validation errors (just like if validation fails and the request was made with ajax), and if not, return the redirect with input.

2 likes
cbj4074's avatar

@somnathsah That won't solve the problem, because in the use-case I describe, I had never logged-in to begin with. I had come to the site, left it open overnight, and then tried to login the next day without refreshing the page first. It should not be the user's responsibility to "always remember to refresh the page before you try to login!"

Furthermore, the lack of an error message when login fails due to an expired CSRF token is unacceptable. This seems obvious, but some kind of error message should accompany any form submission failure in a web application.

This is easy to fix. And there is no need even to show an error message.

As I said in the OP, when the user submits the login form, check the response in JS for a token expiry error. If such an error is present, make another AJAX request to the server to request a new CSRF token, and then in the callback, update the login form with that new token, and re-submit the form automatically.

This fixes the issue, in all scenarios, and it's completely transparent to the user.

jlrdw's avatar

poor user experience

I am not totally disagreeing, however coming from business programming and not a user experience programming, I firmly believe in every system a user should log out if leaving the computer.

On a State of Texas employee computer you broke the law if you did not log out.

To me that should be a web standard not an option to have to log out.

And I could care less what a client wants, If a client has that kind of mindset and and does not understand the importance of logging out I would not even want such a customer.

I have done well enough that I can pick and choose.

To me that's no different than never trust a user input.

But again I don't totally disagree if you want to program a non logout system, that's fine.

cbj4074's avatar

@jlrdw That all seems like an irrelevant corollary. We're talking about coming to this site, doing something else for a couple of hours (or however long the CSRF token expiry might be), and then trying to log in and the process failing without explanation.

jlrdw's avatar

Agreed Jeffrey should do a fix.

Please or to participate in this conversation.