Spread the love

Laravel by default protects the application from unauthorized commands executed from outside the application means a suspicious user wanted to perform form submission from external command. But Laravel by default creates a token for every post request which we need to verify before reaching to out application logic.

TokenMismatchException is related to CSRF(Cross-site request forgeries). whenever a post request come to the Laravel application, Laravel executes app/Http/Middleware/VerifyCsrfToken.php middleware and checks if the token is same or not. If the passed token is missing or not match it throws an error TokenMismatchException.

Thus, to eliminate this issue we can use two solutions.

  1. Add csrf token in Ajax request using csrf_token() function in post payload
  2. Exclude the url from csrf middleware.

Add Csrf token in Ajax request

In this method we will add csrf token to our Ajax call as below

Example 1 : Add a key _token in request payload of ajax

Simplest way to add the token in post request payload using _token key and value from Laravel function {{ csrf_token() }}.

$.ajax({
        method: 'POST',
        url: '/form-submit',
        data: {
            'name': 'Test',
            'lastName': 'last',
            '_token': '{{ csrf_token() }}'
        },
        success: function(response){
            console.log(response);
        },
        error: function(jqXHR, textStatus, errorThrown) { 
            console.log(JSON.stringify(jqXHR));
            console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
        }
    });

As you can see we have passed the '_token': '{{ csrf_token() }}‘ extra param to data key.

Example 2 : Attach the token in header of Ajax request

In this example i will add the token in Ajax header option and get the value of token from meta tag.

$.ajax({
        method: 'POST',
        url: '/form-submit',
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
        data: {
            'name': 'Test',
            'lastName': 'last',
        },
        success: function(response){
            console.log(response);
        },
        error: function(jqXHR, textStatus, errorThrown) { 
            console.log(JSON.stringify(jqXHR));
            console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
        }
    });

Here we added the header and X-CSRF-TOKEN and passed the value from meta tag.

 headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
 },

By default Laravel add below code to every page of our application so we can get the csrf token from our meta tags and can attach to Ajax call.

<meta name="csrf-token" content="ZMZoxRkuNFEy5PYr2otg5dCdUYq0BGGZAmiL2NaH">

Example 3 : Token in form and serialize the form in Ajax request

In this example i will use the token in form and will serialize the form in Ajax request so let’s create a form first

 <form method="POST" id="formSubmit"  accept-charset="UTF-8"  >
     {{ csrf_field() }}
    <input id="name" name='name' maxlength="70" placeholder="Name" required  type="email"  > 
    <input id="last_name" name='last_name' maxlength="70" placeholder="Last Name" required  type="email"  > 
    <button type="submit" >  Submit </button>
</form>

Now, we have added {{ csrf_field() }} to our form it will create a hidden field with name _token and value of Laravel csrf token.

Now handle the form submit in jquery.

$(document).on("submit",'#formSubmit',function(){
  $.ajax({
        method: 'POST',
        url: '/form-submit',
        data:  $(this).serialize(),
        success: function(response){
            console.log(response);
        },
        error: function(jqXHR, textStatus, errorThrown) { 
            console.log(JSON.stringify(jqXHR));
            console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
        }
    });
   return false;

})

Here, we user $(this).serialize() which will get all inputs of form and send to the server with _token.

Exclude the url from CSRF middleware in laravel

Another solution is to exclude the URL from the CSRF verification middleware(app/Http/Middleware/VerifyCsrfToken.php). This approach is only useful when we wanted to submit or call an api from outside the our application.

So now open app/Http/Middleware/VerifyCsrfToken.php and add url to $except array of class as below

<?php

namespace App\Http\Middleware;

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

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        "form-submit",
        .....
        //
    ];
}

Now you will be able to access your url without adding the csrf token in your request.

Leave a Reply