We need to generate our registrations and sessions controller for Devise at this point as per the Devise docs.
In the console:
$ bin/rails g devise:controllers users -c=registrations
create app/controllers/users/registrations_controller.rb
$ bin/rails g devise:controllers users -c=sessions
create app/controllers/users/sessions_controller.rb
Then, we need to update the file app/controllers/users/registrations_controller.rb:
# frozen_string_literal: true
class Users::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
Inside of the user sessions controller app/controllers/users/sessions_controller.rb, add the following:
# frozen_string_literal: true
class Users::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
The docs also take you through adding reCAPTCHA for the password reset page, but we will skip that part for now.
Configuring our router
Finally, we need to add our recently generated sessions and registrations controllers to the Devise router helper:
Rails.application.routes.draw do
get 'session/index'
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks', sessions: 'users/sessions', registrations: 'users/registrations' }
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
resources :session, only: [:index]
resources :home, only: %i[index create]
# Defines the root path route ("/")
root 'home#index'
end
Testing our application
At this point, we can boot the application back up with bin/dev and attempt to login at http://localhost:3000/users/sign_in. You will see reCAPTCHA load up on the sign in form:
Sign in with reCAPTCHA
First, attempt to sign in a user without selecting reCAPTCHA and you will get a failure message:
Failed sign in
Signing in correctly will work as expected after clicking on the reCAPTCHA form.
Afterwards, you can also sign out and try it on the sign up form to see a similar setup for password registration.
Summary
Today's post demonstrated how to configure Devise with reCAPTCHA for Ruby on Rails 7.
In the next post in the series, we will look at how we can configure the devise_token_auth gem to enable token-based authentication for Rails JSON APIs.