Altcademy - a Forbes magazine logo Best Coding Bootcamp 2023

What is CSRF Protection in Ruby on Rails?

In this blog post, we will go over what CSRF protection is, why it is important, and how it is implemented in Ruby on Rails. We will walk through some real-life examples and provide step-by-step instructions on how to add CSRF protection to your Rails applications. Our goal is to make this topic approachable to beginners in programming, so we will do our best to explain any jargon and provide intuitive analogies to help you understand the concepts.

What is CSRF?

Cross-Site Request Forgery (CSRF) is a type of web application vulnerability where an attacker tricks a user into performing unwanted actions on a web application in which they're authenticated. In other words, a CSRF attack takes advantage of the trust that a web application has in the user's browser.

To better understand CSRF, let's use an analogy. Imagine you're at a coffee shop using a public Wi-Fi network. You log in to your bank's website to check your account balance. Meanwhile, a hacker is sitting at another table on the same network. They notice that you're logged in to your bank's website and decide to take advantage of your authenticated session. They send a request to your bank's website, pretending to be you, and instruct the bank to transfer money from your account to theirs. This would be an example of a CSRF attack.

Now that we have a basic understanding of what CSRF is, let's look at how Rails provides protection against it.

CSRF Protection in Rails

Ruby on Rails, often just called Rails, is a popular web application framework for the Ruby programming language. It is known for its emphasis on convention over configuration, which means that it often provides sensible defaults for developers to work with. One of these defaults is built-in CSRF protection.

Out of the box, Rails includes a security feature called protect_from_forgery, which is enabled by default in every new Rails application. This feature helps to prevent CSRF attacks by adding a unique token to each form in your application. This token is also stored in the user's session. When a form is submitted, the server checks if the token in the form matches the token in the user's session. If they match, the request is allowed to proceed. If they don't match or the token is missing, the server will reject the request.

Here's an example of how this works in practice: Let's say you have a form in your Rails application that allows users to update their email address. With CSRF protection enabled, the form would look something like this when rendered in the user's browser:

<form action="/update_email" method="post">
  <input type="hidden" name="authenticity_token" value="random_token_here">
  <input type="email" name="email">
  <input type="submit" value="Update Email">
</form>

Notice the hidden input field with the name authenticity_token. This is the CSRF token that Rails automatically adds to the form. When the form is submitted, the server will check if the value of the authenticity_token field matches the token stored in the user's session. If they match, the request is allowed to proceed. Otherwise, the server will reject the request.

You may be wondering how the server knows what token to expect. When CSRF protection is enabled, Rails automatically generates a new token for each session. This is done using the form_authenticity_token method, which is called when a new session is created. The generated token is then stored in the user's session and added to any forms in the application.

Customizing CSRF Protection

While the default CSRF protection in Rails is quite robust, you may need to customize it for your specific application. Rails provides several options for customizing its CSRF protection behavior.

Disabling CSRF Protection

In some cases, you may want to disable CSRF protection for specific actions or controllers. For example, if you have an API that is meant to be used by other applications, you may not want to require CSRF tokens for those requests.

To disable CSRF protection for a specific action or controller, you can use the skip_before_action method in your controller. Here's an example of how to disable CSRF protection for a single action:

class ApiController < ApplicationController
  skip_before_action :verify_authenticity_token, only: [:update_email]

  def update_email
    # Your code here
  end
end

In this example, CSRF protection is disabled for the update_email action in the ApiController. It is important to note that disabling CSRF protection should be done with caution, as it can expose your application to CSRF attacks.

Customizing the CSRF Token

By default, Rails uses a secure random value for the CSRF token. However, you may want to use your own token generation logic. To do this, you can override the form_authenticity_token method in your ApplicationController. Here's an example of how to generate a custom token:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  private

  def form_authenticity_token
    # Your custom token generation logic here
  end
end

In this example, you would replace the comment with your own token generation logic. Just make sure that your custom token is sufficiently random and hard to guess.

Handling Invalid CSRF Tokens

When Rails receives a request with an invalid or missing CSRF token, it raises an ActionController::InvalidAuthenticityToken exception by default. You can customize how your application responds to invalid tokens by rescuing this exception in your ApplicationController. Here's an example of how to handle invalid CSRF tokens:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  rescue_from ActionController::InvalidAuthenticityToken do |exception|
    # Your custom response to invalid tokens here
  end
end

In this example, you would replace the comment with your own response logic. This could include rendering an error page, redirecting the user to a different page, or logging the incident for further analysis.

Conclusion

CSRF protection is an essential security feature for web applications, and Rails makes it easy to implement with the protect_from_forgery feature. By default, Rails provides robust CSRF protection out of the box, but also allows for customization when needed.

As a beginner in programming, understanding CSRF protection and how to use it in your Rails applications is an important step in building secure web applications. By following the examples and explanations in this blog post, you should now have a good understanding of CSRF protection in Rails and how to use it effectively in your projects.