Secure CSRF Token Storage in Rails 7 using Encrypted Cookies


What is a CSRF token?

A CSRF token is a unique value that is generated by the server and stored on the client’s session. This token is included in every subsequent request made by the client, either in an HTTP header or as a hidden field on a form submission. The Rails server then compares this token against the one stored in its session store. If the token on the request does not match the one on the server, the request is considered illegitimate and is not processed.

Why do we need to store the CSRF token outside of the session?

The default CSRF protection in Rails stores the token in the user’s session, which is secure but may cause issues when using a cache such as Redis. This is because sessions for unauthenticated users may be created in large numbers, containing only the CSRF token, which can lead to cache thrashing and decreased performance. This may cause eviction of old sessions, which can negatively impact the overall performance of the application.

In order to solve this problem, Rails version 7 introduces a new feature where CSRF tokens are stored in an encrypted cookie rather than the session. This method is more efficient as it only stores tokens for authenticated users.

How to use it?

To use this feature, we need to set config.action_controller.use_custom_csrf_token to a lambda that returns the token to be used for the request. The lambda will then be called with the request object as an argument.

  • Add the below code in config/application.rb to use an encrypted cookie to store the CSRF token.
    config.action_controller.use_custom_csrf_token = lambda do |request|
    request.cookies['csrf_token'] = Encryption.encrypt(request.session[:_csrf_token])
    end
    

Join Our Newsletter