How to Add Cloudflare Turnstile to Your Ruby on Rails Application
Adding protection to your Rails app with Cloudflare Turnstile.
tl;dr - the rails-cloudflare-turnstile
gem1 (GitHub link) is a great way to add Cloudflare Turnstile to your Rails app. Let’s learn how to use it!
Setup
First, install the gem:
If you haven’t enabled Turnstile yet in your Cloudflare account, follow the “Get Started” guide. You’ll need a sitekey and secret key. Make sure to associate it with your domain too - for instance, kristianfreeman.com
- in the Turnstile settings.
Add your sitekey and secret key to your Rails app - I like to use rails credentials:edit
:
My credentials are structured like this:
Create an initializer file, called config/initializers/turnstile.rb
:
Usage
First, we’ll add the Turnstile JS script into an application layout file. If you are super performance-sensitive, you may want to do this specifically on the pages you’re going to use Turnstile. Here, I’ll just add it in app/views/layouts/application.html.erb
:
In your forms, you can use the <%= cloudflare_turnstile %>
partial to embed the Turnstile UI element right into your form. For instance, on a signup page:
Importantly, you also need to validate on the server-side! Speaking as a CF employee who has talked to the Turnstile team, there is a lot of people implementing Turnstile… without the server-side validation.
Users are created in my app in UsersController#create
. Let’s validate the Turnstile data before calling that method:
If the validation fails, the gem will throw an RailsCloudflareTurnstile::Forbidden
exception. You need to rescue_from
that exception in the controller, and do something with that failure. I prefer not to tell users - they’re probably spammers - that their validation against Turnstile’s rules fail.
Turnstile is great - really easy to configure, and literally saving me money by reducing the strain on my servers and ancillary analytics/marketing products, by reducing the number of junk users being added to my app. It only took ~15 minutes to get this implemented on one of my Rails apps, and I’m already seeing results.
Footnotes
-
Not my gem! But it’s great - thanks to Instrumentl for building it. ↩