Search code examples
phpajaxlaravelcsrfmiddleware

Laravel CSRF middleware is not checking X-CSRF-TOKEN request header


Middleware:

use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier {

    public function handle($request, Closure $next)
    {
        return parent::handle($request, $next);
    }

}

Javascript:

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': 'wrong-token-to-test',
        'X-XSRF-TOKEN': 'another-wrong-token-to-test',
    }
});

Blade:

$.ajax({
      method: "POST",
      url: "{{url("login/$user")}}",
      data: {
         "email": $("#email").val(),
         "password": CryptoJS.SHA256($('#password').val()).toString(),
         "_token": "{{csrf_token()}}"
      }
})

Even using the wrong Http header value ('wrong-token-to-test') for csrf token does not result in any token mismatching exception. The request is handled normally. Does that mean Laravel is not checking for the X-CSRF-TOKEN header?


Solution

  • Laravel first tries to get the CSRF token from the parameter called _token in the get or post, and if missing, THEN it tries to get it from a X-CSRF-TOKEN. Here is the implementation logic in the code in /vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken, method tokensMatch :

    $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
    

    But you are already effectively including the _token parameter (and with correct value) in your ajax post:

    "_token": "{{csrf_token()}}"
    

    So it doesn't matter what you send in the X-CSRF-TOKEN header.