reCaptcha Spam Protection - V3 with V2 Fallback
When it comes to the job of keep spam-bots at bay, the first thing that comes to my mind is reCaptcha. I have used it as my go to solution in over 25 projects in the last 8 years. It's popular, battle tested and you can't go wrong choosing it.
Why Use Two Versions at Once
reCaptcha V3 is great. It doesn't add any badge or a checkbox in the client side which keeps it neat. In the server side we will score the request and then choose what to do if it falls in our definition of spam.
In many of the SaaS applications I build, if in doubt we do one or more of SMS confirmation, extensive field validation, manual validation before giving access to resources. But for a simple website that is on a budget this would be an unjustifiable cost.
Instead, when suspicious, we can invalidate the form and re-render it with the V2 "I'm not a robot" checkbox. This way many users will just go through without having an idea they have been vetted and spam will get challenged in a second step.
Before Getting Started
Unfortunately V2 and V3 keys are not compatible with one another. As a result you will have to create 2 reCaptcha applications and use both key pairs at once. The recaptcha gem, which we will be using for this example, can only support one key pair in its initialiser. For the other we will have to use inline configuration.
Create 2 reCaptcha Apps (v2 and v3) here: https://www.google.com/recaptcha/admin/create
Instructions
Add the recaptcha gem to your Gemfile and run bundle install
.
gem 'recaptcha'
Then configure your system in an appropriate way to store the credentials. If you are prior to Rails 5.1 you might use secrets.yml
file or a tool like dot-env-rails or figaro. For newer Rails you have Rails credentials to encrypt the credentials which is a better way to handle secrets. Here I would be simply using environment variables.
export RECAPTCHA_V2_SITE_KEY=...
export RECAPTCHA_V2_SECRET_KEY=...
export RECAPTCHA_V3_SITE_KEY=...
export RECAPTCHA_V3_SECRET_KEY=...
Then I will configure recaptcha gem with the V3 key. This way we only have to override the key when we use V2 methods of the gem.
Recaptcha.configure do |config|
config.site_key = ENV['RECAPTCHA_V3_SITE_KEY']
config.secret_key = ENV['RECAPTCHA_V3_SECRET_KEY']
end
Then we need to update the form to use either V3 or V2 helper methods. To know which we will use the instance variable @show_checkbox_recaptcha
.
- if @show_checkbox_recaptcha
.row.mb-20
.col-xs-12
center = recaptcha_tags(site_key: ENV['RECAPTCHA_V2_SITE_KEY'])
hr
- else
= recaptcha_v3(action: 'register'
Then we need to vet the request in the controller and decide if we need to enable the V2 helper.
class Marketing::RegistrationsController < MarketingController
def create
success = verify_recaptcha(action: 'register')
checkbox_success = verify_recaptcha(secret_key: ENV['RECAPTCHA_V2_SECRET_KEY') unless success
@person = Person.new(registration_params)
if (success || checkbox_success) && @person.save
flash[:success] = 'Account created. Please login to continue.'
redirect_to new_user_session_path
else
@show_checkbox_recaptcha = true unless success
flash[:warning] = @person.errors.any? 'Check form for errors' : 'Please confirm that you are human'
render :new
end
end
end
Thats it! When the user lands on the form for the first time it will not show any reCaptcha. Once the form is submitted and if the score is not satisfactory we will load the V2 "I'm not a robot" checkbox".
Hope it was helpful!
About the Author
Ziyan Junaideen -
Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.