0

Im using "omniauth-google-oauth2" gem to setup google login alongside devise login. Also added an ssl in app root directory as mentioned in a tutorial (File => cacert.pem)

In /config/initializers/omniauth.rb

OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do  
provider :google_oauth2,"google_clent_id", "google_secret_id",{client_options: {ssl: {ca_file:Rails.root.join("cacert.pem").to_s}}} 
end

In /config/initializers/devise.rb

  config.omniauth :google_oauth2, "google_client_id", "google_secret_id", { name: 'google' }

In routes.rb

devise_for :users, :controllers => { sessions: "sessions", registrations: 'registrations',:omniauth_callbacks => "users/omniauth_callbacks" }
  get 'auth/:provider/callback', to: 'sessions#create'
  get 'auth/failure', to: redirect('/')
  get 'signout', to: 'sessions#destroy', as: 'signout'

In controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_action :verify_authenticity_token
  def google_oauth2
      @user = User.from_omniauth(request.env["omniauth.auth"])
      if @user.persisted?
        flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
        sign_in_and_redirect @user, :event => :authentication
      else
        session["devise.google_data"] = request.env["omniauth.auth"]
        redirect_to new_user_registration_url
      end
  end
end

In user.rb

devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :omniauthable,
         :omniauth_providers => [:google_oauth2]
    def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      full_name = auth.info.name.split(" ")
      user.first_name = full_name[0]
      user.last_name = full_name[1]
      user.email = auth.info.email
      user.oauth_token = auth.credentials.token
      user.oauth_expires_at = Time.at(auth.credentials.expires_at)
      user.save!
    end
  end

In sessions_controller.rb

  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = user.id
    redirect_to root_path
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end

In my views (html.erb files)

<% if current_user %>
        Signed in as <strong><%= current_user.name %></strong>!
        <%= link_to "Sign out", signout_path, id: "sign_out" %>
      <% else %>
        <%= link_to "Sign in with Google", user_google_oauth2_omniauth_authorize_path, id: "sign_in" %>
      <% end %>

When i click on the signin link, Im redirected to google account selection/login page. When I login with an account, the page gets redirected to root path but user has not signed in. But user details has been logged to database user table. And the server log is shown as below,

Started GET "/users/auth/google_oauth2" for 127.0.0.1 at 2018-01-21 15:49:11 +0530
   (0.3ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
(google_oauth2) Request phase initiated.
Started GET "/users/auth/google_oauth2/callback?state=*****&code=4/****" for 127.0.0.1 at 2018-01-21 15:49:16 +0530
(google_oauth2) Callback phase initiated.
Processing by Users::OmniauthCallbacksController#google_oauth2 as HTML
  Parameters: {"state"=>"****", "code"=>"4/****"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."provider" = ? AND "users"."uid" = ? ORDER BY "users"."id" ASC LIMIT ?  [["provider", "google_oauth2"], ["uid", "*****"], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  SQL (3.5ms)  UPDATE "users" SET "oauth_token" = ?, "oauth_expires_at" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["oauth_token", "*********"], ["oauth_expires_at", "2018-01-21 11:19:16"], ["updated_at", "2018-01-21 10:19:17.882842"], ["id", 2]]
   (105.7ms)  commit transaction
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 2], ["LIMIT", 1]]
Redirected to http://localhost:3000/
Completed 302 Found in 220ms (ActiveRecord: 111.1ms)


Started GET "/" for 127.0.0.1 at 2018-01-21 15:49:18 +0530
Processing by HomeController#index as HTML
  Rendering home/index.html.erb within layouts/application
  Rendered layouts/sliders/_slider_home.html.erb (0.4ms)
  Rendered customers/_index.html.erb (1.6ms)
  Rendered home/index.html.erb within layouts/application (3.4ms)
  Rendered layouts/header/_style_files.html.erb (0.3ms)
  Rendered layouts/_meta_files.html.erb (1.5ms)
  Rendered layouts/logos/_logo_main.html.erb (1.4ms)
  Rendered layouts/header/_header_search.html.erb (2.5ms)
  Rendered layouts/header/_header_navigation.html.erb (0.6ms)
  Rendered layouts/logos/_logo_secondary.html.erb (1.1ms)
  Rendered layouts/footer/_footer.html.erb (2.3ms)
  Rendered layouts/static/_hover_top.html.erb (0.4ms)
  Rendered layouts/footer/_script_files.html.erb (1.1ms)
Completed 200 OK in 727ms (Views: 724.5ms | ActiveRecord: 0.0ms)

For security reasons , some fields are changed to astericks(****). User info is saved into the 'users' table in database without even asking any permissions. But why does not the user get logged in ? My regular devise login forms are also not working. Please help e understand what am i doing wrong here ? Thanks in advance.

2 Answers2

2

If anyone comes behind, for me the issue was that I was missing the 1.9.1 in my gemfile. Adding that fixed the issue for me. I spent hours checking my code for typos, but it was the gem all along.

gem "omniauth", "~> 1.9.1" gem "omniauth-google-oauth2"

atayl16
  • 23
  • 4
0

Your code seems pretty fine. But I think in routes.rb you should add call back as additional parameter

devise_for :users, controllers: { 
omniauth_callbacks: 'users/omniauth_callbacks' 
}

and bind to or create the user

def self.from_omniauth(access_token) 
data = access_token.info 
user = User.where(email: data['email']).first 
# Uncomment the section below if you want users to be created if they don't exist 
# unless user 
# user = User.create(name: data['name'], # email: data['email'],
 # password: Devise.friendly_token[0,20] # ) 
# end 
user 
end

Do not use this configuration in

config/initializers/omniauth.rb:

Rails.application.config.middleware.use 
OmniAuth::Builder do 
provider :google_oauth2, 
  ENV['GOOGLE_CLIENT_ID'],
  ENV['GOOGLE_CLIENT_SECRET'] 
end

define your application id and secret in 

config/initializers/devise.rb

For additional permissions you can use

Rails.application.config.middleware.use
 OmniAuth::Builder do 
provider :google_oauth2, 
ENV['GOOGLE_CLIENT_ID'], 
ENV['GOOGLE_CLIENT_SECRET'],
 { 
name: 'google', 
scope: 'email, profile, plus.me, http://gdata.youtube.com', 
prompt: 'select_account',
 image_aspect_ratio: 'square', 
image_size: 50
 }

end

if you alter

config.omniauth :google_oauth2, 
ENV["GOOGLE_ID"],
ENV["GOOGLE_SECRET"]

The server won't even start. However issue seemed to be in a passed parameter to this in

config.omniauth :google_oauth2, ENV["GOOGLE_ID"], ENV["GOOGLE_SECRET"],
    { :name => "google", # this is the line that was giving me trouble
    :scope => "email",
    :prompt => "select_account",
    :image_aspect_ratio => "square",
    :image_size => 50 }

I think you are altering the way in which the auth was returned i.e.

:google => {:name => "foo", :email => "bar@email.com" }

altering and then mismatching the routes. The devise generated

user_google_oauth2_omniauth_authentication_path

is still pointing to

users/auth/google_oauth2/authentication

but the marked line in the arguments made the oauth expect

users/auth/google/authentication
Alok Amme
  • 129
  • 1
  • 4
  • 1
    After trying out this solution , i got another error. Redirected to a page showing ***"Not found. Authentication passthru."*** when clicked on signin link. –  Jan 21 '18 at 12:02
  • What error you are getting currently? I think code should work. It worked for me. – Alok Amme Jan 21 '18 at 12:04
  • 1
    When I click on the Sign in link, I get redirected to a page , which shows ***Not found. Authentication passthru*** . –  Jan 21 '18 at 12:33
  • devise_for :users, path: "auth", :controllers => {sessions: 'sessions', registrations: 'registrations', omniauth_callbacks: 'omniauth_callbacks'} – Alok Amme Jan 21 '18 at 13:01
  • Recheck your route matching.I have added the approach in solution – Alok Amme Jan 21 '18 at 14:04
  • I was getting the `passthru` error because I was configuring the provider as `google` instead of `google_oauth2` – Andrespch Oct 13 '18 at 17:36