Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react with Rails 5, getting CSRF error for post with axios

I'm trying to use react_on_rails to build my first example with react and rails. I'm trying to save some data to the rails backend, using axios for the 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 the 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 that when I click the submit, 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):

For one, I don't understand why the parameters seem to be passed twice, but that's not even generating a warning, so don't care for now.

The problem is that I don't see a way to obtain the CSRF tokens in my react code to use in the post requests

should I just disable CSRF? or is there a better way?

like image 435
Don Giulio Avatar asked Jul 07 '17 13:07

Don Giulio


Video Answer


2 Answers

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Rails handles CSRF attacks by appending authenticity_token to every Non-GET requests(POST,PUT/PATCH and DELETE). The error means you are not sending authencity_token in the request params, You should append an unique authenticity_token to the params, something like "authuenticity_token" => "BsfdgtZ1hshxgthjj" which should resolve the issue.

like image 106
Pavan Avatar answered Sep 25 '22 07:09

Pavan


react_on_rails deals with this issue by providing two helpers. From the react_on_rails documentation:

Rails has built-in protection for Cross-Site Request Forgery (CSRF), see Rails Documentation. To nicely utilize this feature in JavaScript requests, React on Rails provides two helpers that can be used as 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);
like image 29
amliving Avatar answered Sep 25 '22 07:09

amliving