15
votes

I am trying to make a http post using fetch api. Even though I am sending the token, I am getting error TokenMismatchException in VerifyCsrfToken.php . How can I make the call using fetch api? (I also tried with jQuery ajax and its working perfectly) Heres the fetch api code

      var URL = $("#form").attr("action");
      var token = $("input[name='_token']").val();
      var group_id = $(this).val();
  fetch(URL, {
       method: 'post',
       mode: 'no-cors',
       body: JSON.stringify({
           'csrf-token': token,
           'group_id': group_id
       })
     }).then(function(response){
           return response.json();
       })  .then(function(json){



       })
         .catch(function(error){


         });

I have added token in form like this

<form id="form" action="{{ url('api/getcoursebygroup') }}">
    <input type="hidden" name="_token" id="csrf-token" value="{{ Session::token() }}" />
  </form>

This jQuery ajax call is working fine :

$.ajax({
          type: "POST",
          url:  URL,
          data: { "group_id" : group_id, "_token" : token },
          dataType: 'json'
      }).done(function (result) {

        if(result.code == 1){



        }


      });

jQuery ajax call headers

enter image description here

Fetch api call headers

enter image description here

6
Which laravel version? For 5.* its should be csrf-token instead of _tokenGONG
hm... can u compare xhr of both requests in dev tools?GONG
its working with _token rather than csrf-token when i make jquery ajax call I am using laravel 5.2Abhishek Kumar
sorry it was my bad. I'm confused it with meta nameGONG

6 Answers

22
votes

I may be late to the party but this works too

    fetch("/audio/signed", {
      headers: {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "X-Requested-With": "XMLHttpRequest",
        "X-CSRF-Token": $('input[name="_token"]').val()
      },
      method: "post",
      credentials: "same-origin",
      body: JSON.stringify({
        key: "value"
      })
    })
17
votes

I was able to make it work.

There were 2 changes I have to make

1) Fetch Api don't use cookie by default. So to make it use cookie I added

credentials: "same-origin"

2)the data need to be submitted in Form data format rather than json

so here's my working code

       var URL = $("#form").attr("action");
       var token = $("input[name='_token']").val();
       var group_id = $(this).val();

      fetch(URL, {
       method: 'post',
       credentials: "same-origin",
       body: new FormData(document.getElementById('form'))
     }).then(function(response){
           return response.json();
       })  .then(function(json){

         // change course

       })
         .catch(function(error){


         });
10
votes

index.blade.php

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

app.js

const csrfToken = document.head.querySelector("[name~=csrf-token][content]").content;

function orderPost(order) {
    fetch('/orders', {
        method: 'post',
        body: JSON.stringify(order),
        headers: {
            'Content-Type': 'application/json',
            "X-CSRF-Token": csrfToken
        }
    })
    .then(response => {
        return response.text();
    })
    .then(text => {
        return console.log(text);
    })
    .catch(error => console.error(error));
};

OrderController.php

public function store(Request $request){
    $order = new Order();
    $order->user_id = $request->json('user_id');
    $order->item_list = $request->json('item_list');
    $order->leave_note = $request->json('leave_note');
    $order->total = $request->json('total');
    $order->save();

    $response = [
        'status' => 'success',
        'message' => 'order stored',
];

    return response()->json($response);
}

1
votes
function post(id){

        const token = '{{ csrf_token() }}';
        web = "{{request()->getHttpHost()}}" ;
        url = 'http://' + web + '/metodo';

        fetch(url, {
            method: 'post',
            credentials: "same-origin",
            headers: {
                'Content-Type': 'application/json',
                "X-CSRF-Token": token
            },
            body: JSON.stringify({
                key: id
            })
            }).then(response => {
                return response.json();
            }).then(text => {
                return console.log(text);
            }).catch(error => console.error(error));

    }
0
votes

After some research, here is what should do a trick for you:

var myHeaders = new Headers({
  "X-CSRF-TOKEN": $("input[name='_token']").val()
});

var URL = $("#form").attr("action");
  var token = $("input[name='_token']").val();
  var myInit = {
   method: 'post',
   headers: myHeaders,
   mode: 'no-cors',
   body: JSON.stringify({
       'group_id': group_id
   };
  var group_id = $(this).val();
  fetch(URL, myInit)
})
.then(function(response){
       return response.json();
})  .then(function(json){



})
.catch(function(error){


});

Also it will not work if you have Chrome < 41

-1
votes

If you are using Form, remember to add

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

or if using blade buttons:

{{ Form::token() }}

Adding this anywhere (usually top of body) will be sufficient for all your JavaScript driven buttons. If you are using blade to generate the form, this is automatically added, so don't have to do this.

And change _token to csrf-token as mentioned by GONG