0

Submitting a form requires a token which the receiving server has named authenticity_token and is expecting a string that is known only to posting and receiving servers:

<input id="authenticity_token" name="authenticity_token" type="hidden" value="ac513de198a9f0536df5003fb5ba3122d1ee53d5" />

that value renders if I call an instance or global variable. However, even though the controller is set with the following filter:

  skip_before_action :verify_authenticity_token, only: [:reservation]

whether I try

<%= form_tag('https://test.webten.net/form') do %>
<%= hidden_field_tag :authenticity_token, @ppayment.authenticity_token, id: "authenticity_token" %>

or

<%= tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: @ppayment.authenticity_token) %>

or

<input id="" name="authenticity_token" type="hidden" value="ac513de198a9f0536df5003fb5ba3122d1ee53d5" />

Rails ends up squashing each value with its own session setting value and rendering:

<input type="hidden" name="authenticity_token" id="authenticity_token" value="ydi5En1ywUkN5VsYIBXu6JTbQmXtwxNhpKlyjbbLi3RdvCc+A59EdDZvroGsGFplAAE5ATLcSqw25LVQkyPtKw==">
<input type="hidden" name="authenticity_token" value="ydi5En1ywUkN5VsYIBXu6JTbQmXtwxNhpKlyjbbLi3RdvCc+A59EdDZvroGsGFplAAE5ATLcSqw25LVQkyPtKw==">
<input id="authenticity_token" name="authenticity_token" type="hidden" value="ydi5En1ywUkN5VsYIBXu6JTbQmXtwxNhpKlyjbbLi3RdvCc+A59EdDZvroGsGFplAAE5ATLcSqw25LVQkyPtKw==">

How can rails default behaviour be overridden in this controller action?

Jerome
  • 5,583
  • 3
  • 33
  • 76
  • Add some code showing how you're calling `form_for`, `form_tag` or `form_with` in your view. These all have an `:authenticity_token` argument that you may need to override. – Aaron Breckenridge Mar 15 '18 at 17:23
  • I have updated the question to include `form_tag` in use – Jerome Mar 15 '18 at 17:33
  • have you read this post https://stackoverflow.com/questions/4085136/how-to-generate-authenticitytoken-on-rails there is a `<%= form_authenticity_token %>` and maybe by following that example you can get this to work? I'll try to help you more. Just let me know – Fabrizio Bertoglio Mar 15 '18 at 19:49
  • I've seen this types of suggestions. The problem here is setting the authenticity_token to a fixed value, NOT the current session's authenticity token. i.e. the value needs to be set at `ac513de198a9f0536df5003fb5ba3122d1ee53d5` – Jerome Mar 15 '18 at 19:51

2 Answers2

0

You have to override the :authenticity_token argument in the form_tag call to prevent Rails from adding the session's authenticity token by default:

<%= form_tag('https://test.webten.net/form', authenticity_token: 'ac513de198a9f0536df5003fb5ba3122d1ee53d5') do %>

or:

<%= form_tag('https://test.webten.net/form', authenticity_token: false) do %>
  <%= hidden_field_tag 'authenticity_token', 'ac513de198a9f0536df5003fb5ba3122d1ee53d5' %>

If that doesn't work, you probably have some JS that overwrites the authenticity token you provided from the one in the META tag. Search for 'csrf-token' in your JS.

See http://guides.rubyonrails.org/form_helpers.html#forms-to-external-resources for more information.

Aaron Breckenridge
  • 1,723
  • 18
  • 25
  • I had tried both those variants in the form tag. also, the string 'csrf-token' does not appear in any JS code, wither in views or assets directories. In every instance, the value is overwritten by the session crsf-token placed in the header `` – Jerome Mar 15 '18 at 22:40
  • would there be a way to hard code the desired string with escaping et al? `` I have not succeded at that either... – Jerome Mar 15 '18 at 22:44
  • You could hard code it with your own `META` tag in the `app/views/layouts/application.html.erb`. Do you use the `jquery-rails` gem? It provides `jquery_ujs` in `app/assets/javascripts/application.js`. – Aaron Breckenridge Mar 16 '18 at 13:37
0

[this answer is complementary to the preceeding one. It solves the issue, but in an inelegant manner]

Various possible avenues of solution appear incomplete / off the mark

  • form_authenticity_tokenis a view helper that returns the current session's authenticity token. Too late to act upon that as the layout may already invoke it
  • most voted response has a per action method protect_from_forgery for ignoring it for internal purposes. Still is too late as session already has issued it
  • a skip before action is just like the previous solution, too late, session token is issued
  • The rails guide is incorrect in stating: authenticity_token: 'external_token'

Aaron Breckenridge's answer provide a clue: "you probably have some JS that overwrites the authenticity token ", supported by this posting. Thus one could search the content of app directory and still not find a JS handler... when jquery-ujs, for example, is gem installed. Based on observed behaviour, it must be getting fired up every time it encounters name='authenticity-token' and sets the value based on the META tag (logical. why have 2 different tokens on same page...) - doing its job properly!

Literally, that token must not be generated upstream. So modifying the layout's header section:

<% unless  request.path == "/controller/action" %>
  <%= csrf_meta_tags %>
<% end %>

is a working solution. This solution gets pollution-prone for multiple paths. Another requires multiple layout handling... thus, file under 'kludgey'. (willing to entertain better one!)

Jerome
  • 5,583
  • 3
  • 33
  • 76