Protecting Applications from CSRF attacks with Ruby on Rails

What is a CSRF Attack?

CSRF stands for a Cross-Site Request Forgery attack. Through malicious links on websites, popups, emails, etc., users are tricked into unknowingly performing malicious actions of the attacker’s choosing.

Because it sneaks malicious actions into requests of users that are authenticated, I like the think of CSRF attacks as parasitic.

The damage that a CSRF attack can cause is related to (1) whether or not developers have added defenses against this type of attack and (2) the type of user account. For example, if the attack is achieved on a regular user’s account it can force the user to change their account information like their email or password, transfer funds, etc. If the attack is achieved on an administrative user’s account, the entire application can be put at risk.

Protecting against CSRF attacks with the Rails App

By default Ruby on Rails attaches a CSRF security token to the HTML document it serves up from its View. Using CSRF security tokens in the header prevents attacks because if they have to be validated by the backend server, attackers cannot create valid requests.

We send a CSRF security token with non-GET requests like Post, Update, and Delete. For non-GET requests we include headers. In these headers, we can send back the CSRF security token to verify it. The Ruby on Rails Application verifies the token on the server and throws an exception if the security token doesn’t match what’s expected.

Here’s what it looks like in practice:

onSubmit(event) {
const url = "/api/v1/dogs/create";
const { name, owner, age} = this.state;

if (name.length == 0 || owner.length == 0 || age.length == 0)

const body = {

const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "POST",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json"
body: JSON.stringify(body)
.then(response => {
if (response.ok) {
return response.json();
throw new Error("Bad network response");
.then(response => this.props.history.push(`/dog/${}`))
.catch(error => console.log(error.message));

Using the Fetch API to send the our HTTP request, we can include "X-CSRF-Token": token as a header. The token, which we defined above the fetch call as const token = document.querySelector('meta[name="csrf-token"]').content, is queried from the metadata of the HTML document that Rails rendered by default when it served up the View.

Full-Stack Software Engineer, Designer, and salsa dancer.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Using Unity game engine to make non-game apps

Gist about Microservices(Container)

How to install flutter | Flutter tutorial

10 Items That Will Help You Be Road Ready This Winter

Automated Environments: Making Smarter Devices

Is premature optimization really the root of all evil?

In-House Software vs SaaS: What’s the Difference and Which Is Better?

Cloud vs On-premise DAM and Image Management

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Lydia Gregory

Lydia Gregory

Full-Stack Software Engineer, Designer, and salsa dancer.

More from Medium

How To Fix A Critical Remote Code Execution Vulnerability In Elementor- CVE-2022–1329


Site is up and running now

Rmap: Nmap Scanning in Ruby

Easy Understanding of Owasp Top 10-2021