8

I ran into multiple difficulties with CSRF when building a small SPA with Laravel and Vue.js:

  • I use index.html as the only view, the rest is handled by vue-router using single file components (i.e. .vue files)
  • Because I'm not using PHP or Blade on the front, I can't inject csrf_token() into my view. Even if I did, the token would eventually expire, yet because the app has no (or very few) page refresh(es), it wouldn't know if the token changed, and it would eventually fail to make AJAX requests with the old token
  • Some answers suggest to pass the token in a cookie and then retrieve it with JS. This approach suffers from the same problem as above -- the SPA is never notified when the token changes
  • I could dig in the internal workings of Laravel and throw an event every time the token changes; the front-end could use Laravel Echo to listen to the changes, but then the question raises, is it even worth to bother?
  • Lastly, I was suggested to use JWT; however, as I understand, JWT is used for authentication purposes, while CSRF -- for every single request regardless of the HTTP verb or intent.

With the last two points in mind, do you think it is necessary/advisable to use a CSRF token in a Laravel SPA? And if so, what would be the best implementation (cookie with the token, dedicated route returning the token, or other)? If not, what are the alternatives?

Alex
  • 3,719
  • 7
  • 35
  • 57
  • Just a thought on your 3rd item: If Laravel changes the CSRF token through cookies and you have a `interceptor` on Vue that will always retrieve the cookie, will it still retrieve the old CSRF because the page was not reloaded? Wouldn't the browser receive the cookie change of the Ajax request? – Marco Aurélio Deleu May 28 '17 at 21:24
  • Another thought: You could have Laravel add a custom HTTP Header on every request that gets intercepted by Vue and stores it for the next Request. The application boot up with a valid CSRF passed by Blade. The 1st Ajax will end containing the token that should be used next. – Marco Aurélio Deleu May 28 '17 at 21:25
  • @MarcoAurélioDeleu Can you expand on your idea with interceptors? I believe it requires `vue-resource` package, which was de-facto superseded with Axios in Vue 2.0? Could you give a code example? It would be much appreciated – Alex May 28 '17 at 21:45

1 Answers1

8

Comments don't have enough space, so I'm adding this as an answer, but this is just a concept as I have extremely low experience with Vue.


From the docs

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });

So the concept would be something like this:

  • Set a custom header from Laravel.
  • When building/starting up your Vue application, get the custom header and set it somewhere global.
  • When making a request, intercept it and add the CSRF token from the global storage

    axios.interceptors.request.use(function (config) { // Get your token from the place you stored it and add to the request });

  • Intercept the response and store a new token

    axios.interceptors.response.use(function (response) { // Store the new CSRF token in the same place you stored the 1st one. });

  • Loop forever

Marco Aurélio Deleu
  • 4,279
  • 4
  • 35
  • 63