1

I use a package installed with Composer in my Laravel project. It contains some JS code for file uploads. In at least one case, the uploads fail because there is no CSRF token sent with the request.

I hope to solve this problem without editing the vendor code. This is the relevant JS:

self.upload = function (file, filename) {
  var formData = new FormData();
  formData.append('file', file, filename);
  formData.append('field', JSON.stringify(field));
  formData.append('contentId', H5PEditor.contentId || 0);

  // Submit the form
  var request = new XMLHttpRequest();
  request.upload.onprogress = function (e) {
    if (e.lengthComputable) {
      self.trigger('uploadProgress', (e.loaded / e.total));
    }
  };

  // ...

}

Is there a way to make Laravel automatically send a CSRF token with a request like this?

With Axios, I'd do

window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': window.Laravel.csrfToken,
    'X-Requested-With': 'XMLHttpRequest'
};

With jQuery, I'd do

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

But in my case, no such library is used.

Pida
  • 928
  • 9
  • 32
  • I do'nt see why you wouldn't use axios or $.ajax, but [the answer here](https://stackoverflow.com/questions/37963758/how-do-i-set-a-default-header-for-all-xmlhttprequests) might help you. – TKoL Aug 10 '20 at 10:18
  • Thanks, I'll check that out. The code above is installed as a Composer dependency, that's why I'd not like to change it. – Pida Aug 10 '20 at 10:21
  • oh i see. Yeah, the answer i linked to might not be exactly recommended, but i don't think there's another way to set default headers with XMLHttpRequest, so you might have to do it – TKoL Aug 10 '20 at 10:33
  • Do you have any idea where to place the code from the other question in a Laravel app? I used it in `bootstrap.js`, then did `npm run dev`, but didn't manage to add any headers yet... – Pida Aug 10 '20 at 12:21
  • 1
    Just try to run it while your page is running live first, in chrome console. Then do something that would make the request happen and check in the network tab if the header was added. That would be the first step. – TKoL Aug 10 '20 at 14:38
  • It's not working in the console (or in any file). You'd look for the additional header in *Headers / Request Headers*, right? – Pida Aug 11 '20 at 05:34
  • 1
    Yeah, that's where you'd look. The answer overrides the `open` method, but the code you're calling may not actually use the `open` method. – TKoL Aug 11 '20 at 10:09
  • It does use that method. Code encapsulation seems to play a role in my problem. I explain this in another question: https://stackoverflow.com/questions/63354643 – Pida Aug 11 '20 at 10:12

1 Answers1

1

You need to have

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

in your page

and then in your code you can use the query selector

document.querySelector('meta[name="csrf-token"]')['content']

to get the value, please use the "fetch" api, so you can append the header.

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Headers

Menawer
  • 843
  • 4
  • 12
  • This is not enough. Your answer shows how to send the token to a HTML page, but my question is how to send it back to the server in an AJAX request: https://laravel.com/docs/7.x/csrf#csrf-x-csrf-token – Pida Aug 10 '20 at 11:25