0

Before going into more detail about the title, I just want to describe the problem at a basic level. I'm getting the dreaded 422, Unprocessable Entity error (ActionController::InvalidAuthenticityToken) after asynchronous requests in my app. What's the best way to handle this?

Loads of answers will say do:

skip_before_action :verify_authenticity_token 

(which is now skip_forgery_protection in Rails 6), and then usually in the comments people get way more upvotes asking about whether or not that's a security risk. There are probably 5 threads like that.

The alternatives to doing this though, is sending the csrf token along with the POST request. So, most answers say make sure to include these headers

'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest'

and also a csrf token like:

'X-CSRF-Token': csrfToken

The issue is getting the csrf token itself. I've tried displaying the contents of the header object with

  const getHeaders = () => {
     let headers = new window.Headers({
     'Content-Type': 'application/json',
     'Accept': 'application/json',
     'X-Requested-With': 'XMLHttpRequest'
  })

  const csrfToken = document.head.querySelector("[name='csrf-token']")
  if (csrfToken) { headers.append('X-CSRF-Token', csrfToken) }

  return headers
}

and

  let headers = getHeaders();
  headers.forEach(function(value, name) {
  console.log(name + ": " + value);
  });

and that doesn't work. I'm guessing however I'm actually getting the token isn't working. Namely:

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

What's the best way to do this with plain ol' JavaScript, no other libraries? I've tried other suggestions and methods to attempt to get the token but so far all have failed. I'm assuming this lives somewhere on my browser but where? I can see all the data in Redux dev tools so the issue is definitely just this token as opposed to sending the correct data correctly (not to mention skip_forgery_protection completely solves it).

In the mean time sadly skip_forgery_protection works perfectly fine added to my Rails controllers, as security isn't the biggest concern in this stage, but I would rather fix the token issue. Thanks!

  • `document.head.querySelector("[name='csrf-token']").content` ? Without `content` at the end you send an object in the headers. – razvans Oct 08 '21 at 08:50
  • @razvans That solution isn't working for me – Hans Foster Oct 08 '21 at 19:05
  • @HansFoster did you ever get this working? I've been going in circles with trying to get a react/rails-api working with omniauth – Coderama Dec 05 '22 at 21:37
  • Did you see this using getAttribute('content'): https://stackoverflow.com/questions/54808071/cant-verify-csrf-token-authenticity-rails-react? An application I worked on used something like this and it worked for all cases except integration tests – dtluther Apr 04 '23 at 02:39

0 Answers0