ruby-on-rails - invalid - rails generate csrf token
Understanding the Rails Authenticity Token (7)
I am running into some issues regarding the Authenticity Token in Rails, as I have many times now.
But I really don't want to just solve this problem and go on. I would really like to understand the Authenticity token. Well, my question is, do you have some complete source of information on this subject or would you spend your time to explain in details here?
What is CSRF?
The Authenticity Token is a countermeasure to Cross-Site Request Forgery (CSRF). What is CSRF, you ask?
It's a way that an attacker can potentially hijack sessions without even knowing session tokens.
- Visit your bank's site, log in.
- Then visit the attacker's site (e.g. sponsored ad from an untrusted organization).
- Attacker's page includes form with same fields as the bank's "Transfer Funds" form.
- Attacker knows your account info, and has pre-filled form fields to transfer money from your account to attacker's account.
- When form gets submitted, browser includes your cookies for the bank site, including the session token.
- Bank transfers money to attacker's account.
- The form can be in an iframe that is invisible, so you never know the attack occurred.
- This is called Cross-Site Request Forgery (CSRF).
- Server can mark forms that came from the server itself
- Every form must contain an additional authentication token as a hidden field.
- Token must be unpredictable (attacker can't guess it).
- Server provides valid token in forms in its pages.
- Server checks token when form posted, rejects forms without proper token.
- Example token: session identifier encrypted with server secret key.
- Rails automatically generates such tokens: see the authenticity_token input field in every form.
authenticity_token is required
authenticity_tokenis required in case of idempotent methods like post, put and delete, Because Idempotent methods are affecting to data.
Why It is Required
It is required to prevent from evil actions. authenticity_token is stored in session, whenever a form is created on web pages for creating or updating to resources then a authenticity token is stored in hidden field and it sent with form on server. Before executing action user sent authenticity_token is cross checked with
authenticity_tokenstored in session. If
authenticity_tokenis same then process is continue otherwise it does not perform actions.
When the user views a form to create, update, or destroy a resource, the Rails app creates a random
authenticity_token, stores this token in the session, and places it in a hidden field in the form. When the user submits the form, Rails looks for the
authenticity_token, compares it to the one stored in the session, and if they match the request is allowed to continue.
Why it happens
Since the authenticity token is stored in the session, the client cannot know its value. This prevents people from submitting forms to a Rails app without viewing the form within that app itself.
Imagine that you are using service A, you logged into the service and everything is ok. Now imagine that you went to use service B, and you saw a picture you like, and pressed on the picture to view a larger size of it. Now, if some evil code was there at service B, it might send a request to service A (which you are logged into), and ask to delete your account, by sending a request to
http://serviceA.com/close_account. This is what is known as CSRF (Cross Site Request Forgery).
If service A is using authenticity tokens, this attack vector is no longer applicable, since the request from service B would not contain the correct authenticity token, and will not be allowed to continue.
API docs describes details about meta tag:
CSRF protection is turned on with the
protect_from_forgerymethod, which checks the token and resets the session if it doesn't match what was expected. A call to this method is generated for new Rails applications by default. The token parameter is named
authenticity_tokenby default. The name and value of this token must be added to every layout that renders forms by including
csrf_meta_tagsin the HTML head.
Keep in mind, Rails only verifies not idempotent methods (POST, PUT/PATCH and DELETE). GET request are not checked for authenticity token. Why? because the HTTP specification states that GET requests is idempotent and should not create, alter, or destroy resources at the server, and the request should be idempotent (if you run the same command multiple times, you should get the same result every time).
Also the real implementation is a bit more complicated as defined in the beginning, ensuring better security. Rails does not issue the same stored token with every form. Neither does it generate and store a different token every time. It generates and stores a cryptographic hash in a session and issues new cryptographic tokens, which can be matched against the stored one, every time a page is rendered. See request_forgery_protection.rb.
authenticity_token to protect your not idempotent methods (POST, PUT/PATCH, and DELETE). Also make sure not to allow any GET requests that could potentially modify resources on the server.
EDIT: Check the comment by @erturne regarding GET requests being idempotent. He explains it in a better way than I have done here.
What is an authentication_token ?
This is a random string used by rails application to make sure that the user is requesting or performing an action from the app page, not from another app or site.
Why is an authentication_token is necessary ?
To protect your app or site from cross-site request forgery.
How to add an authentication_token to a form ?
If you are generating a form using form_for tag an authentication_token is automatically added else you can use
<%= csrf_meta_tag %>.
Authenticity Token is rails' method to prevent 'cross-site request forgery (CSRF or XSRF) attacks'.
To put it simple, it makes sure that the PUT / POST / DELETE (methods that can modify content) requests to your web app are made from the client's browser and not from a third party (an attacker) that has access to a cookie created on the client side.
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.
If you are simply having difficulty with rails denying your AJAX script access, you can use
<%= form_authenticity_token %>
to generate the correct token when you are creating your form.
You can read more about it in the documentation.
Authenticity Token is so important, and in Rails 3.0+ you can use
<%= token_tag nil %>
<input name="authenticity_token" type="hidden" value="token_value">