jQuery add CSRF token to all $.post() requests' data jQuery add CSRF token to all $.post() requests' data ajax ajax

jQuery add CSRF token to all $.post() requests' data


From Laravel documentation:

You could, for example, store the token in a "meta" tag:

Once you have created the meta tag, you can instruct a library like jQuery to add the token to all request headers. This provides simple, convenient CSRF protection for your AJAX based applications:

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

So for example you can do request like below.

Add this meta tag to your view:

<meta name="csrf-token" content="{{ csrf_token() }}">

And this is an example script which you can communicate with Laravel (sends request when you click an element with id="some-id" and you can see the response in an element with id="result"):

<script type="text/javascript">    $(document).ready(function(){        $.ajaxSetup({            headers:            { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }        });        $("#some-id").on("click", function () {            var request;            request = $.ajax({                url: "/your/url",                method: "POST",                data:                {                    a: 'something',                    b: 'something else',                },                datatype: "json"            });            request.done(function(msg) {                $("#result").html(msg);            });            request.fail(function(jqXHR, textStatus) {                $("#result").html("Request failed: " + textStatus);            });        });    });</script>


Your $.ajaxPrefilter approach is a good one. You don't need to add a header, though; you simply need to add a property to the data string.

Data is provided as the the second argument to $.post, and then formatted as a query string (id=foo&bar=baz&...) before the prefilter gets access to the data option. Thus, you need to add your own field to the query string:

var csrf_token = $('meta[name="csrf-token"]').attr('content');$.ajaxPrefilter(function(options, originalOptions, jqXHR){    if (options.type.toLowerCase() === "post") {        // initialize `data` to empty string if it does not exist        options.data = options.data || "";        // add leading ampersand if `data` is non-empty        options.data += options.data?"&":"";        // add _token entry        options.data += "_token=" + encodeURIComponent(csrf_token);    }});

This will turn id=userID into id=userID&_token=csrf_token.


Generally I agree with the concept Kornel suggested except one thing.

Yes, Laravel's docs advice to use $.ajaxSetup, but it's not recommended since this method affects all the subsequent ajax requests. It is more correctly to set the ajax settings for each request. Though you can re-set stuff:

All subsequent Ajax calls using any function will use the new settings, unless overridden by the individual calls, until the next invocation of $.ajaxSetup()

If you use $.ajax(), it's more convenient to utilize either data property or headers. Laravel allows CSRF-token both as a request parameter or a header.

First, you add the following meta tag into the view

<meta name="csrf-token" content="{{ csrf_token() }}">

And then make an ajax request either way:

$.ajax({    url: "/your/url",    method: "POST",    data:    {        a: 'something',        b: 'something else',        _token: $('meta[name="csrf-token"]').attr('content')    },    datatype: "json"});

OR

$.ajax({    url: "/your/url",    method: "POST",    data:    {        a: 'something',        b: 'something else',    },    headers:     {        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')    }    datatype: "json"});