On same page of a rails 4 app I have a
in the head:
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="some_token" />
and below in the body:
<form action="/someaction" method="post">
<input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="_method" value="patch" />
<input type="hidden" name="authenticity_token" value="another_token" />
The csrf token is need for js calls. But why is the form token different from the csrf token? Which of the two tokens is used on form submission?
Yes, using tokens is the only way to protect reliably against CSRF attacks. Whether a protection is required or not depends on the actions the program does with the submitted data. As a rule of thumb: If data is modified with the permissions or context of the current user, you need the protection.
Briefly, Cross-Site Request Forgery (CSRF) is an attack that allows a malicious user to spoof legitimate requests to your server, masquerading as an authenticated user. Rails protects against this kind of attack by generating unique tokens and validating their authenticity with each submission.
The authenticity token is designed so that you know your form is being submitted from your website. It is generated from the machine on which it runs with a unique identifier that only your machine can know, thus helping prevent cross-site request forgery attacks.
A CSRF Token is a secret, unique and unpredictable value a server-side application generates in order to protect CSRF vulnerable resources. The tokens are generated and submitted by the server-side application in a subsequent HTTP request made by the client.
I've made some researches to answer your question, and here are results.
First of all, let's look at this part:
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="some_token" />
This part is generated by method csrf_meta_tags. From the source code we can see that:
"content" attribute value of <meta name="csrf-param" />
is taken from request_forgery_protection_token, and, by default, is :authenticity_token
.
"content" attribute value of <meta name="csrf-token" />
is taken from form_authenticity_token method, where the token is either taken from session, or generated.
Now let's check out this part:
<input type="hidden" name="authenticity_token" value="another_token" />
From the source we can see that:
extra_tags_for_form
invokes token_tag method.token_tag
method takes the token as the argument.token
argument for token_tag
is previously extracted from options
argument of form_tag method in html_options_for_form method.So if you didn't manually set authenticity_token
param in options
to your custom token and didn't meet the conditions that lead to setting token
value to false (will be mentioned below), token_tag
method will receive nil
and invoke the same form_authenticity_token method that is used for the <meta name="csrf-token" />
tag creating. By the way, for filling name
attribute of input it also uses request_forgery_protection_token, that is used when <meta name="csrf-param" />
tag generation occurs.
And because this all occurs during the same request, invocation of form_authenticity_token
method should return the same result in both cases.
Which of the two tokens is used on form submission?
On form submission will be used the token from hidden input.
Token from <meta />
also can be used, but only if all of below conditions (that make token
argument of token_tag
method be set to false) will be met:
:remote => true
should be passed in options
of form_tag
.embed_authenticity_token_in_remote_forms
config is set to false.authenticity_token
wasn't passed in options
.But why is the form token different from the csrf token?
As for this question, maybe this problem occurs because of caching. Or, probably, if you use Turbolinks gem, it might cause this issue (you can check this if you totally refresh the page and compare tokens once again). For more info about problem with Turbolinks, check this question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With