1

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

Wes Foster
  • 8,202
  • 4
  • 36
  • 57
Fi3n1k
  • 693
  • 3
  • 10
  • 20
  • 1
    Doesn't look like you're setting a CSRF token. Use Rails' `form_tag` helper – Wes Foster Jan 10 '16 at 22:24
  • Possible duplicate of [Can't verify CSRF token authenticity in rails](http://stackoverflow.com/questions/11986939/cant-verify-csrf-token-authenticity-in-rails) – Cristiano Mendonça Jan 10 '16 at 22:26
  • 2
    @CristianoAlencar: That answer is more along the lines of an external API request. This seems to be an internal server request, which should just use the Rails CSRF conventions. As @WesFoster mentioned, using `form_tag` will properly set the token. Here's a good SO post I found that explains this CSRF stuff well: http://stackoverflow.com/questions/941594/understanding-the-rails-authenticity-token. – dwenzel Jan 10 '16 at 22:31

1 Answers1

6

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.

Community
  • 1
  • 1
dwenzel
  • 1,286
  • 7
  • 13