Rails CSRF Protection with React
A simple approach to handling CSRF tokens with Ruby on Rails and React when using the webpacker gem
Note: For an up-to-date answer on this topic, check out the original github thread the code examples below are based on:
Rails has built in CSRF protection by default, so when you first try to make a post request from your React code, initially your request will fail and you'll probably see a message like this in your console:
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity
ActionController::InvalidAuthenticityToken
The Quick & Dirty Solution
The easier but more reckless fix you may want to do is to simply disable CSRF protection in your rails controller, which can be done like so:
skip_before_action :verify_authenticity_token
This will 'fix' the issue, but it will also potentially open your app up to non-authentic requests.
An Alternate Solution?
Let's assume you have an App component in your React code that looks like this:
import React from 'react'
import axios from 'axios'
class App extends React.Component {
handleSubmit = (e) => {
e.preventDefault()
axios.post(url, payload)
.then( (resp) => console.log(resp))
.catch( (error) => console.log(error))
}
render(){
return(
<form onSubmit={this.handleSubmit}>
<button type="submit">Click Me</button>
</form>
)
}
}
export default App
What we can try to do is tweak this code to add our CSRF token to the headers in our request by modifying axios' default headers:
import React, { Component } from 'react'
import axios from 'axios'
class App extends React.Component {
handleSubmit = (e) => {
e.preventDefault()
const csrfToken = document.querySelector('[name=csrf-token]').content
axios.defaults.headers.common['X-CSRF-TOKEN'] = csrfToken
axios.post(url, payload)
.then( (resp) => console.log(resp))
.catch( (error) => console.log(error))
}
render(){
return(
<form onSubmit={this.handleSubmit}>
<button type="submit">Click Me</button>
</form>
)
}
}
Adding that to your code should resolve the CSRF issues in your app and allow you to now make post requests from your React code to your Rails controllers.
Conclussion
The above example is specific to a rails app using the webpacker gem, and uses axios for the solution -- if you are not using webpacker and/or axios, YMMV with this.