JoseCarlosVM
JoseCarlosVM

Reputation: 121

Can't setup simple OAuth2 between Google and toy website using Ruby on Rails, Devise, Omniauth

I am trying to learn Ruby on Rails by building a small web application. My first step was to start with OAuth login so users could login using Facebook, Google etc. But when I go to the /users/sign_up devise page on my localhost and click on Sign in with GoogleOauth2, it "does nothing" and the console tells me:

D, [2021-10-05T04:55:04.716439 #10144] DEBUG -- omniauth: (google_oauth2) Request phase initiated.
W, [2021-10-05T04:55:04.730086 #10144]  WARN -- omniauth: Attack prevented by OmniAuth::AuthenticityTokenProtection
E, [2021-10-05T04:55:04.730681 #10144] ERROR -- omniauth: (google_oauth2) Authentication failure! authenticity_error: OmniAuth::AuthenticityError, Forbidden

I've setup devise and omniauth-google-oauth2, and registered an app in the Google developer console, adding the appropriate callback uris as http://127.0.0.1:3000/users/auth/google_oauth2/callback and http://localhost:3000/users/auth/google_oauth2/callback, and wrote the key and secret to .env using the dotenv gem to read them, running the server with dotenv rails server.

I'd like to understand what is wrong here, why, how would I go about debugging this, and how to fix it so that logging in through Google takes me to my homepage, the "Yay! You're on rails!" screen.

My files are setup as such:

routes.rb:

Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth' }
end

app/models/users.rb:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise  :database_authenticatable, :registerable,
        :recoverable, :rememberable, :validatable,
         :timeoutable,
        :omniauthable, omniauth_providers: [:google_oauth2]

  def self.create_from_google_data(provider_data)
    where(provider: provider_data.provider, uid: provider_data.uid).first_or_create do | user |
      user.email = provider_data.info.email
      user.password = Devise.friendly_token[0, 20]
      user.skip_confirmation!
    end
  end
end

app/config/initializers/devise.rb:

...
config.omniauth :google_oauth2, ENV['GOOGLE_APP_ID'], ENV['GOOGLE_APP_SECRET'], scope: 'userinfo.email,userinfo.profile'
...

app/controllers/users/omniauth_controller.rb

class Users::OmniauthController < ApplicationController
    def google_oauth2
        @user = User.create_from_google_data(request.env['omniauth.auth'])
        if @user.persisted?
          sign_in_and_redirect @user
          set_flash_message(:notice, :success, kind: 'Google') if is_navigational_format?
        else
          flash[:error] = 'There was a problem signing you in through Google. Please register or try signing in later.'
          redirect_to new_user_registration_url
        end 
    end
    def failure
        flash[:error] = 'There was a problem signing you in. Please register or try signing in later.' 
        redirect_to new_user_registration_url
    end
end

app/config/initializers/session_store.rb:

Rails.application.config.session_store :active_record_store, key: '_devise-omniauth_session'

Please let me know if any further clarification is needed to debug this issue.

Upvotes: 1

Views: 456

Answers (1)

JoseCarlosVM
JoseCarlosVM

Reputation: 121

For anyone stumbling upon the same issue, I solved it by adding the following gem to the project, after trying tons of fixes I found online: gem "omniauth-rails_csrf_protection" Why? No clear idea. Answers with more explanation would be very welcome.

Upvotes: 1

Related Questions