React with Rails 5 getting CSRF error for post with axioms
I am trying to use react_on_rails
to build my first react and rails example. I am trying to store some data in a rails backend using axios for ajax.
here's my code:
import store from "../store/helloWorld";
import axios from "axios";
export const SAVE_NAME = "SAVE_NAME";
export function saveNameAction(name) {
return {
type: SAVE_NAME,
name
};
}
export function saveName(name) {
axios
.post("/hello_world", saveNameAction(name))
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
}
and component:
import PropTypes from "prop-types";
import React from "react";
import * as actions from "../actions/helloWorld";
export default class HelloWorld extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired // this is passed from the Rails view
};
/**
* @param props - Comes from your rails view.
*/
constructor(props) {
super(props);
this.state = { name: this.props.name };
}
updateName(name) {
this.setState({ name: name });
}
handleSubmit(event) {
event.preventDefault();
actions.saveName(this.state.name);
}
render() {
return (
<div>
<h3>
Hellopp, {this.state.name}!
</h3>
<hr />
<form>
<label htmlFor="name">Say hello to:</label>
<input
id="name"
type="text"
value={this.state.name}
onChange={e => this.updateName(e.target.value)}
/>
<input
type="submit"
value="Submit"
onClick={event => this.handleSubmit(event)}
/>
</form>
</div>
);
}
}
The problem is when I click submit button my backend reports
Started POST "/hello_world" for ::1 at 2017-07-07 15:30:44 +0200
Processing by HelloWorldController#create as HTML
Parameters: {"type"=>"SAVE_NAME", "name"=>"Stranger", "hello_world"=>{"type"=>"SAVE_NAME", "name"=>"Stranger"}}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
First, I don't understand why the parameters seem to be passed twice, but that don't even generate a warning, so now don't worry.
The problem is I don't see a way to get CSRF tokens in my react code to use in requests post
Should I turn off CSRF? or is there a better way?
source to share
ActionController :: InvalidAuthenticityToken (ActionController :: InvalidAuthenticityToken):
Rails handles CSRF attacks by adding Non-GETs (POST, PUT / PATCH, and DELETE) authenticity_token
to every request . The error means that you are not passing in the request parameters, you must add a unique to , something like that should fix the problem.authencity_token
authenticity_token
params
"authuenticity_token" => "BsfdgtZ1hshxgthjj"
source to share
I found I react_on_rails
have a helper system for handling CSRF tokens,
it mainly uses:
<%= csrf_meta_tags %>
to add csrf_token to headers on the page as meta
and then you can use:
import ReactOnRails from "react-on-rails";
export function saveNameAction(name) {
console.log("creating action " + name);
return {
authenticity_token: ReactOnRails.authenticityToken(),
type: SAVE_NAME,
name
};
}
to extract it and use it.
source to share
react_on_rails
handles this problem by providing two helpers. From the react_on_rails
documentation :
Rails has built-in security for the cross-site request framing (CSRF) routine, see the Rails Documentation. To make good use of this feature in JavaScript requests, React on Rails provides two helpers that can be used like the following for POST, PUT, or DELETE requests:
import ReactOnRails from 'react-on-rails';
// reads from DOM csrf token generated by Rails in <%= csrf_meta_tags %>
csrfToken = ReactOnRails.authenticityToken();
// compose Rails specific request header as following { X-CSRF-Token: csrfToken, X-Requested-With: XMLHttpRequest }
header = ReactOnRails.authenticityHeaders(otherHeader);
source to share