CSRF token InvalidAuthenticityToken

I tried to use a fetch(… method: ‘PUT’) and I’m getting an InvalidAuthenticityToken error. I’m guessing this has something to do with the csrf token. Has anyone fixed this problem ?

1 Like

Are you using the jquery_ujs or the rails_ujs gem?

In my application I’m using jquery_ujs and haven’t had any issues with authenticity tokens.

1 Like

You can query your <meta name="csrf-token"> element for the token and include it in the request’s headers:

fetch(…, {
  method: "PUT",
  credentials: "same-origin",
  headers: {
    "X-CSRF-Token": getMetaValue("csrf-token")
  },
  …
})

function getMetaValue(name) {
  const element = document.head.querySelector(`meta[name="${name}"]`)
  return element.getAttribute("content")
}
9 Likes

That’s what I ended up doing. I wasn’t sure if that was the best practices.
What was curious though…
document.querySelector(meta[name="${name}"]).content #=> worked
however;
$(meta[name="${name}"]).content #=> didn’t work work in a debugger in the stimulus controller. If I let the page finish loading, it does work :confused:

@scottharvey I’m using the gem, but stimulus is in webpack… so those don’t crossover do they ?

jquery_ujs has installation instructions for webpack so it should work but I haven’t tried using Webpack.

1 Like

Just to add my 2 cents to this thread, in a Rails app you can also use Rails-ujs ajax function. It is my understanding that it automatically includes the CSRF token for you.

As an example here is what I have been using in an app:

const data = new FormData();
data.append("myModelName[field]", value);

Rails.ajax({
  url: "/my_post_url",
  type: "POST",
  data
});
1 Like

I have fixed this in the past using the rails-ujs module:

import { Controller } from 'stimulus'
import Rails from 'rails-ujs'

export default class extends Controller {
  connect() {
    fetch('/some/url', {
      method: 'PUT',
      credentials: 'same-origin',
      headers: { 'X-CSRF_Token': Rails.csrfToken() }
    })
  }
}
2 Likes

Quick update in 2023 for anyone landing on this page.

The Ruby on Rails Guide (for v7) suggests using FetchRequest from the library @rails/request.js. This will automatically include the CSRF token in requests.

import { FetchRequest } from '@rails/request.js'
...
async myMethod () {
  const request = new FetchRequest('post', 'localhost:3000/posts', {
    body: JSON.stringify({ name: 'Request.JS' })
  })
  const response = await request.perform()
  if (response.ok) {
    const body = await response.text
  }
}

If you’re using another http request library, the token can be included in the request header by querying the meta tag (as others suggested)

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