Fi3n1k
Fi3n1k

Reputation: 891

Error: Can't verify CSRF token authenticity rails

I am submitting a form in Rails4 from Modal. This solution was working fine in Rails 3.x

The code is as following:

 <div class="modal fade" id="copy-product-addons">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">×</button>
        <h4>Copy Add-Ons From:</h4>
      </div>
      <div class="modal-body">
        <form id="addons-copy" method="POST" action="<%= copy_addons_product_path(@product) %>">
          <%= select_tag "from", options_from_collection_for_select(@shop.enabled_products - [@product], 'id', 'name'),  :class => "form-control %>
        </form>
      </div>
      <div class="modal-footer">
        <a href="#" class="btn btn-danger" data-dismiss="modal">Cancel</a>
        <a href="#" onclick="$('#addons-copy').submit(); return false;" class="btn btn-primary">Copy Add-ons</a>
      </div>
    </div>
  </div>
</div>
<% end %>

As a response, instead of executing specific action it re-directs me to Login page by login me out.

The response in terminal looks like:

> Started POST "/products/10168/copy_addons" for 127.0.0.1 at 2016-01-10
> 21:19:10 +0100 Processing by ProductsController#copy_addons as HTML  
> Parameters: {"from"=>"10130", "id"=>"10168"} Can't verify CSRF token
> authenticity Redirected to http://myr-d.dev/login Filter chain
> halted as :require_login rendered or redirected

Thank you

Upvotes: 1

Views: 1870

Answers (1)

dwenzel
dwenzel

Reputation: 1434

In Rails 4, there are conventions that prevent CSRF attacks for HTML requests. This SO post explains the general concept well: Understanding the Rails Authenticity Token

It looks like your Controller is checking for a CSRF token, but your form is not sending one. That is because you are using a manual <form> tag in your view, which does not contain the required hidden token.

If you use Rails form_tag helper method, Rails will automatically generate the authenticity token for you that will then be sent along as part of the form:

<div class="modal-body">
  <%= form_tag(copy_addons_product_path(@product), id: "addons-copy") do %>
    <%= select_tag "from", options_from_collection_for_select(@shop.enabled_products - [@product], 'id', 'name'),  :class => "form-control %>
  <% end -%>
</div>

If you inspect the HTML that will get generated from this, you'll see a hidden input tag; something like this:

<input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />

This is how the token gets sent as part of the form. Then your Controller will compare this with the current token to verify there is no CSRF attempt, and you should no longer encounter this error.

Upvotes: 6

Related Questions