Search code examples
laravellaravel-5csrf

Encountering "TokenMismatchException in VerifyCsrfToken.php" error


I am attempting to perform an AJAX submission to Laravel. According to Laravel's documentation here, I need to add a CSRF token as both a request header and POST parameter. I'm retrieving the CSRF Token from the XSRF-TOKEN cookie as also described in the documentation:

// Grab XSRF cookie.
var csrf_token;
var cookies = document.cookie.split(';');
for(cookie_offset in cookies) {
    var cookie_parts = cookies[cookie_offset].split('=');
    if(cookie_parts[0].trim() === 'XSRF-TOKEN') {
        csrf_token = cookie_parts[1].trim();
    }
}

This retrieves a token similar to the following: eyJpdiI6Ik96QTdtcFIzam85TGJNQ3pzNUF1blE9PSIsInZhbHVlIjoiQm8zelBSaFpaM0JZcjlxcURFVEZNenZWMzNxUHFBMm1VVzM3YXpBbjVvaTBReEY5cFA1RGV3UVBHQWhjVGhZYmtDZ2lacGxFejJwQkxHaGplV1wvVEtRPT0iLCJtYWMiOiI3NTlkZmI5ODU2YTdlN2RiYTA1YTAyM2NiZmZlOWUwZTQyY2I0NTUzOWEyNzI5YjE2ODIyMmU1YzZiNDE1MmQ0In0

Once I have the token, I am adding it as a X-CSRF-Token header and _token POST parameter.

When I perform the request, I'm receiving this error: TokenMismatchException in VerifyCsrfToken.php line 46

I've also tried passing the token as a X-XSRF-TOKEN header instead, but am getting the same error

When I set the X-XSRF-TOKEN and omit the _token POST parameter, I encounter a different error: DecryptException in Encrypter.php line 142: Invalid data.

What is it that I am missing here?

UPDATE: After some more debugging and comparing this request with requests being generated by an AngularJS implementation which ran side-by-side this implementation, I discovered the problem was that I needed to URL Decode the cookie's value.

I simply needed to do the following, after extracting the csrf token from the cookies:

csrf_token = decodeURIComponent(csrf_token );


Solution

  • You add the token to the client's request either for AJAX or as a hidden field in a form. You have to add a way for the client to know what the token is. One method is to use the token meta tag from the base view:

    <meta name="xsrf-token" content="{{Session::token()}}" />
    

    Then in your javascript side for any ajax request you can do:

    $(document).ready(function(){
      $.ajaxSetup({
         headers: {
           'X-CSRF-Token':$('meta[name="xsrf-token"]).attr('content')
         }
      });
    }
    

    Otherwise when you post you can use the CSRF token in a hidden field as so:

    <input type="hidden" name="_token" value="{{Session::token()}}">