I. What is CSRF in Rails and How Does It Work?
CSRF (Cross-Site Request Forgery) is a type of attack where an attacker tricks a user into performing unintended actions on a web application in which the user is authenticated. In Rails, CSRF protection is implemented to prevent such attacks. This article explains what CSRF is, how it works in Rails, and the mechanisms used to prevent CSRF attacks.
- Attack Scenario: An attacker creates a malicious website that contains a form or script that sends a request to a target website where the user is authenticated.
- User Interaction: The attacker tricks the user into visiting the malicious website, which automatically submits the form or executes the script.
- Unintended Actions: The request sent to the target website contains the user’s session cookie, allowing the attacker to perform actions on behalf of the user without their consent.
II. How CSRF Works in Rails
CSRF Token Generation: Every time a Rails view is rendered, a CSRF token is generated by the application. This token is unique to each session and is embedded in forms and AJAX requests.
Token Inclusion in Forms: The CSRF token is automatically included in forms generated by Rails helpers such as
form_with
,form_for
, andform_tag
. It’s also included in AJAX requests made by Rails withdata-csrf
attribute.Token Verification: When a form is submitted or an AJAX request is made, the CSRF token is sent along with the request. Rails automatically compares this token with the token stored in the session. If the tokens match, the request is processed normally. If they don’t match or the token is missing, Rails raises an exception, usually
ActionController::InvalidAuthenticityToken
.SameSite Cookie Attribute: Rails also supports configuring the SameSite attribute for cookies, which further helps mitigate CSRF attacks. By setting the SameSite attribute to
:strict
or:lax
, Rails ensures that cookies are only sent with same-site requests, preventing CSRF attacks originating from other sites.
Note: the SameSite attribute is supported in Rails 5.2 and later versions.
# config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_your_app_session', same_site: :strict
There are diffirent default same_site values in between browsers. E.g. Chrome 80+ default value is Lax
and Firefox 72+ default value is Strict
. You can set the same_site value to :none
to disable the SameSite attribute.
# config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_your_app_session', same_site: :none
How to SameSite attribute works:
:strict
: Cookies are only sent in a first-party context (i.e., same-site requests).:lax
: Cookies are sent in a first-party context and with safe cross-site requests (e.g., GET requests).:none
: Cookies are sent in all contexts, including cross-site requests.
III. Conclusion
CSRF protection in Rails relies on the generation and verification of CSRF tokens. By including a unique token in each form and request, Rails ensures that only requests originating from the same site and session are accepted, effectively preventing CSRF attacks. This built-in protection mechanism helps secure Rails applications against common web security threats.
Public comments are closed, but I love hearing from readers. Feel free to contact me with your thoughts.