Skip to content

How To: Use Recaptcha with Devise

Simon Perrier edited this page Jun 14, 2022 · 63 revisions

To add Google's reCAPTCHA to your site:

Install reCAPTCHA gem

Please see reCAPTCHA gem for installation details and API key setup.

Some of the available options for #verify_recaptcha can be found here.

Add reCAPTCHA to views

Add recaptcha_tags for reCAPTCHAv2 (or recaptcha_v3 for reCAPTCHAv3) to the forms you want to protect and show reCAPTCHA error.

Example for a page app/views/devise/registrations/new.html.erb

<%= flash[:recaptcha_error] %>
<%= recaptcha_tags %> # <%= recaptcha_v3(action: 'signup') %> for v3

For details on how to edit devise views see configuring-views.

Add reCAPTCHA verification in controllers

Include a prepend_before_action for any action you want to secure:

Devise::RegistrationsController

To add reCAPTCHA in registration page, create a app/controllers/registrations_controller.rb or generate it using rails g devise:controllers users -c=registrations

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect.

  private

  def check_captcha
    return if verify_recaptcha # verify_recaptcha(action: 'signup') for v3

    self.resource = resource_class.new sign_up_params
    resource.validate # Look for any other validation errors besides reCAPTCHA
    set_minimum_password_length

    respond_with_navigational(resource) do
      flash.discard(:recaptcha_error) # We need to discard flash to avoid showing it on the next page reload
      render :new
    end
  end
end

and configure devise for using your controller changing config/routes.rb

devise_for :users, controllers: { ... , registrations: "registrations", ... }

Devise::SessionsController

To add reCAPTCHA in login page, create a app/controllers/sessions_controller.rb or generate it using rails g devise:controllers users -c=sessions

class SessionsController < Devise::SessionsController
  prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect.

  private

  def check_captcha
    return if verify_recaptcha # verify_recaptcha(action: 'login') for v3

    self.resource = resource_class.new sign_in_params

    respond_with_navigational(resource) do
      flash.discard(:recaptcha_error) # We need to discard flash to avoid showing it on the next page reload
      render :new
    end
  end 
end

and configure devise for using your controller changing config/routes.rb

devise_for :users, controllers: { ... , sessions: "sessions", ... }

Devise::PasswordsController

To add reCAPTCHA in password reset page, , create a app/controllers/passwords_controller.rb or generate it using rails g devise:controllers users -c=passwords

class PasswordsController < Devise::PasswordsController
  prepend_before_action :check_captcha, only: [:create]

  private

  def check_captcha
    return if verify_recaptcha # verify_recaptcha(action: 'password/reset') for v3

    self.resource = resource_class.new

    respond_with_navigational(resource) do
      flash.discard(:recaptcha_error) # We need to discard flash to avoid showing it on the next page reload
      render :new
    end
  end
end

and configure devise for using your controller changing config/routes.rb

devise_for :users, controllers: { ... , passwords: "passwords", ... }

Notes

Follow these instructions also if you are using devise generated controller (rails g devise:controller [scope]). In this case the route to use in devise_for is registrations: "user/registrations" and passwords: "user/passwords"

Clone this wiki locally