Search code examples
ruby-on-railsdeviseoauth-2.0

rail+devise+devise-google-oauth redirect to google login when visit restricted url


I'm using Devise with omniauth-google-oauth2 gem. I only want to implement google sign_in. This is my user model:

#app/models/user.rb
class User < ActiveRecord::Base

  devise :omniauthable, :omniauth_providers => [:google_oauth2]
  attr_accessible :email

  def self.find_for_google_oauth2(access_token, signed_in_resource=nil)
    data = access_token.info
    user = User.where(:email => data["email"]).first
    unless user
      user = User.create(email: data["email"] )
    end
    user
  end
end

routes file:

#config/routes.rb
Booking::Application.routes.draw do
  #https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview#using-omniauth-without-other-authentications
  devise_for :users , controllers: {omniauth_callbacks: "users/omniauth_callbacks"}
  devise_scope :user do
    get 'sign_in', :to => 'devise/sessions#new', :as => :new_user_session
    get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
  end

  resources :events
end

according with official docs I have this line in my events_controller.rb

before_filter :authenticate_user!, except: [:index, :show]

Problem: If i visit events/new the app want to redirect me in /sign_in and this is the error:

Started GET "/events/new" for 127.0.0.1 at 2013-12-04 20:50:56 +0100
Processing by EventsController#new as HTML
Completed 401 Unauthorized in 0ms


Started GET "/sign_in" for 127.0.0.1 at 2013-12-04 20:50:56 +0100
Processing by Devise::SessionsController#new as HTML
  Rendered /home/cristiano/.rvm/gems/ruby-1.9.2-p320@booking/gems/devise-3.2.2/app/views/devise/sessions/new.html.erb within layouts/application (13.6ms)
Completed 500 Internal Server Error in 17ms

ActionView::Template::Error (undefined method `session_path' for #<#<Class:0x007f42ecc695b8>:0x007f42ecc65b98>):
    1: <h2>Sign in</h2>
    2: 
    3: <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
    4:   <div><%= f.label :email %><br />
    5:   <%= f.email_field :email, :autofocus => true %></div>
    6:

I want to redirect the user in the user_omniauth_authorize_path(:google_oauth2) url and not in the sign_path url becouse i only use the google login and i have no local sign_in/sign_up

SOLUTION:

copy all views to my application:

rails generate devise:views

Edit app/views/devise/sessions/new.html.erb removing all contents and appendig the link to google authentication:

#app/views/devise/sessions/new.html.erb
<%= link_to "Sign in with Google", user_omniauth_authorize_path(:google_oauth2) %>

Thanks to gregates


Solution

  • So sending to the new_user_session_path or the root_path if that's undefined is built into the devise failure app. If you want to change this behavior, you'll need to customize that app. Here is a somewhat old but still relevant guide to customizing this behavior by using a custom failure app: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated

    However, in my opinion you should create a custom view at the new_user_session_path (i.e., app/views/devise/sessions/new.html.erb that prompts your user to sign in with google, rather than simply automatically signing them in. If you just send them to the user_omniauth_authorize_path(:google_oauth2) AND they've already authorized your app AND they have a current google session, then they'll just be automatically signed in with no prompt, which to me is bad UX.