However if the session has already timed out, and the user clicks logout (which triggers a POST to the logout route) a token mismatch error is received. It makes sense - the token doesn't match, because the session has expired.

I can just catch that particular TokenMismatchException based on the request variables, and if so, continue them on their merry way (to the logged out redirect path, say "home" or "/"). Like this:

My question is: if I do the above, what is the point of the token in the first place? And how to you logout a user when their session has expired while maintaining the intended outcomes of using a POST logout with a CSRF token?

1 Answer
1

The middleware that checks authentication should run before the middleware that checks the validity of the CSRF token.

That way, when the session has expired, you never get to the CSRF check in the first place because you have already checked for session expiration in the authentication middleware and done the redirect to the login page there.

This will not affect the CSRF protection of valid sessions logging out, because the valid session will make it through the authentication middleware.

By default, the Laravel middleware runs the CSRF check first. However, it should be easy to reorder them to work the other way.

For Laravel 5.7:

In Laravel 5.7, the Illuminate\Foundation\Http\Kernel class has a new field:

Middleware classes that appear in this field are always run in the order in which they appear. The default setting for this field is shown above. (The Laravel starter project has only one change to this list: \App\Http\Middleware\Authenticate::class instead of \Illuminate\Auth\Middleware\Authenticate::class.)

If you add the CSRF middleware to the list (anywhere below the authentication middleware), that should ensure that it always runs in the order you want.

That makes a lot of sense actually. I'm using the default routes for auth, and all sit outside of (by default) of the auth middleware, but do sit within the web middleware. I will give them a shuffle around now, and come back with your answer if your right. Curious though why the default behaviour is for the logout route to be outside of the auth middleware
– ChrisFeb 8 '17 at 4:12

It's not that the default behavior is for the logout route to be outside the auth middleware. It's that the auth middleware for authentication routes is set in the authentication controller's constructor by default, so it runs after the regular list of middleware.
– Moshe KatzFeb 8 '17 at 12:18

Ah yeah, I never swapped to controller level middleware, so forget that they exist tbh. I only use route level or route provider level middleware. Feels more consistent and visible for me.
– ChrisFeb 8 '17 at 12:27

@MosheKatz - A year later, using Laravel 5.7. Can you provide any detail on how to reorder the authentication check before the CSRF check? I tried editing Kernel.php and moving $middlewareGroups to the end of the class but that had no effect. Thanks!
– stackingjasoncooperFeb 19 at 15:00