CSRF token protection in Laravel

A while back I wrote about handling CSRF tokens with ajax calls to Laravel. I have re-vamped my philosophy since then. All routes should have protection, not just a few. This ensures that I

  1. Never accidentally leave a route unprotected
  2. Reduce complexity in my routes. Don’t worry about which routes are protected or unprotected.

How do I do it? It’s actually quite simple. We start by ignoring all GET requests. Next we handle the X-CSRF-Token header for ajax requests since those need to be protected too.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Route::filter('csrf', function($route, $request)
{
if (strtoupper($request->getMethod()) === 'GET')
{
return; // get requests are not CSRF protected
}

$token = $request->header('X-CSRF-Token') ?: Input::get('_token');

if (Session::token() !== $token)
{
throw new Illuminate\Session\TokenMismatchException;
}
});

To protect everything we just need to wrap a group around all our routes. This really shouldn’t affect performance too much and leaving parts of your site unprotected has far worse consequences than running this extra small weight filter for all routes.

1
2
3
4
5
6
7
8
Route::group(['before' => 'csrf'], function()
{
Route::get('/', 'HomeController@index');
Route::post('login', 'AuthController@store');
Route::any('logout', 'AuthController@destroy');

Route::resource('users', 'UserController');
});