zquestz / omniauth-google-oauth2

Oauth2 strategy for Google
1.46k stars 414 forks source link

How I authenticate to different types of users using same authentication callback url? #375

Closed jivKrishna closed 5 years ago

jivKrishna commented 5 years ago

Hey can anyone resolve my problem? The problem is that I want to authenticate two types of user "Admin" and "Viewer". so, I have created two separate actions in SessionsController like:

class SessionsController < ApplicationController def create_admin auth = request.env["omniauth.auth"] session[:omniauth] = auth.except("extra") user = Admin.find_by(provider: auth["provider"], uid: auth["uid"]) unless user user = Admin.create( name: auth["info"]["name"], email: auth["info"]["email"], image: auth["info"]["image"], provider: auth["provider"], uid: auth["uid"] ) end session[:user_id] = user.id redirect_to root_url, notice: "Signed In as Admin!" end

def create_viewer auth = request.env["omniauth.auth"] session[:omniauth] = auth.except("extra") user = Viewer.find_by(provider: auth["provider"], uid: auth["uid"]) unless user user = Viewer.create( name: auth["info"]["name"], email: auth["info"]["email"], image: auth["info"]["image"], provider: auth["provider"], uid: auth["uid"] ) end session[:user_id] = user.id redirect_to root_url, notice: "Signed In Viewer!" end

def destroy session[:user_id] = nil session[:omniauth] = nil redirect_to root_url, notice: "Signed Out!" end end

and I have created routes like:

Rails.application.routes.draw do get "auth/:provider/callback", to: "sessions#create_admin" get "auth/:provider/callback", to: "sessions#create_viewer"

delete "sign_out", to: "sessions#destroy", as: "sign_out" end

but during admin login or viewer login, I only redirect to "admin" login, please someone help me to resolve my problem...

zquestz commented 5 years ago

Yeah you can't list the same route for the callbacks. This will always go to the admin screen as you have seen. You will need to have just 1 callback method. To figure out if it is an admin or viewer, you can set the state param on the login request. You can set it to something like admin_RAND_NUM, and parse the state in your callback, and initialize the correct type of user. You want to include the random number so the state variable can't be predicted.

This thread can also be useful: https://stackoverflow.com/questions/9890985/passing-parameters-through-omniauth

jivKrishna commented 5 years ago

Thank you for response on my query. Can you give an example, please. I'm beginner so, it's difficult to understand but I'm trying.

Thank you,

zquestz commented 5 years ago

Something like:

def create_user
  is_admin = params['state'].split('_').first == 'admin' : true ? false
  if is_admin
    auth = request.env["omniauth.auth"]
    session[:omniauth] = auth.except("extra")
    user = Admin.find_by(provider: auth["provider"], uid: auth["uid"])
    unless user
      user = Admin.create(
        name: auth["info"]["name"],
        email: auth["info"]["email"],
        image: auth["info"]["image"],
        provider: auth["provider"],
        uid: auth["uid"]
      )
    end
    session[:user_id] = user.id
    redirect_to root_url, notice: "Signed In as Admin!"
  else
    auth = request.env["omniauth.auth"]
    session[:omniauth] = auth.except("extra")
    user = Viewer.find_by(provider: auth["provider"], uid: auth["uid"])
    unless user
      user = Viewer.create(
        name: auth["info"]["name"],
        email: auth["info"]["email"],
        image: auth["info"]["image"],
        provider: auth["provider"],
        uid: auth["uid"]
      )
    end
    session[:user_id] = user.id
    redirect_to root_url, notice: "Signed In Viewer!"
  end
end

And then the following for routes.

Rails.application.routes.draw do
  get "auth/:provider/callback", to: "sessions#create_user"
  delete "sign_out", to: "sessions#destroy", as: "sign_out"
end
jivKrishna commented 5 years ago

Thank you, so much