Integrate facebook login for already registered users - ruby-on-rails

I am integrating facebook login in my application using the example code from the Omniauth documentation
https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
def self.from_omniauth(hash)
where(email: hash.info.email).first_or_create do |user|
user.email = hash.info.email
user.password = Devise.friendly_token[0,20]
user.username = hash.info.name # assuming the user model has a name
end
end
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# render :text => request.env['omniauth.auth'].to_yaml
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
I followed the example as it is. However as the code in omniauth_callbacks_controller I'd say if an user is a new to the application then it should follow the else statement and be redirected to user registration url. However what happens is that a new user is created in the database always. Shouldn't I fall in the else statement in case the user has no account yet in my app?
According to the suggested implementation of the method from_omniauth I understand that first_or_create actually creates a new user in the db using the information from facebook. But if that's the case, what is the use of the else option redirecting to new_user_registration_url?
Anything I am not seeing?

Related

How do I know when a user is registering vs logging in with Devise and Omniauth in Rails

I'm using Rails 6 + Devise for login/registration. Users can register/login with Facebook via omniauth.
I want to log one analytics event when the user logs in, and a different analytics event when they register for the first time.
app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
flash[:log_event] = {
'event_category' => 'engagement',
'event_name' => 'login',
'method' => 'facebook'
}
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
end
The flash[:log_event] is passed to Google Analytics. My problem is that Devise seems to follow the same code path for first registration as it does for a regular login.
I suppose I could check the #user.created_at timestamp, and treat it as a registration if it's a couple of minutes old, but I'm sure there's a cleaner solution.
You can always make your own version of User.from_omniauth. Notice the first_or_initialize instead of ..._create
# in app/models/user.rb
def self.from_omniauth(auth)
user = where(auth.slice(:provider, :uid)).first_or_initialize do |new_user|
new_user.provider = auth.provider
new_user.uid = auth.uid
new_user.username = auth.info.nickname
end
user.image_url = auth.info.image # need to update in case image changed on provider's site
user
end
Then in your controller check for new_record?
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.new_record?
#user.save # Important step I missed earlier
# ... Do some custom thing here for your app
end
if #user.persisted?
# ....

Can't keep new user logged in with omniauth

The first time the User is created but it doesn't keep me logged in, even if I set sign_in #user after creating the Customer, the next time I access it does sign me in.
Am I missing something?
class CallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
if resource.id.blank?
sign_in resource, event: :authentication
set_flash_message(:notice, :success, kind: 'Facebook') if is_navigational_format?
# Create customer
Customer.create(:user_id => resource.id, :name => resource.name, :lastname => resource.lastname)
redirect_to new_user_session_path
else
sign_in resource_name, resource
redirect_to profile_path
end
end
end
So I had to add
session["warden.user.user.key"][0] = resource.id
for a weird reason it wasn't adding the ID from the user to the session.
This worked for me but I don't think is the "way" to do it.

Devise Rails & Admin_Mailer

I'm using devise with my Rails 4 app.
I have the following in my user.rb model:
def send_admin_mail
AdminMailer.new_user_waiting_for_approval(self).deliver
end
def send_user_welcome_mail
AdminMailer.new_user_waiting_for_access(user).deliver
end
The first method sends me an email when a new user registers. The aim is for the second method to send a welcome email to the new user. The first method works. The second raises an issue with 'no_method_error' (undefined method email in my callbacks controller).
My callback controller has the following:
def linkedin
#user = User.find_for_linkedin_oauth(request.env["omniauth.auth"])
if #user.persisted?
#user.send_admin_mail
#user.send_user_welcome_mail
redirect_to root_path, :event => :authentication
# sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
# set_flash_message(:notice, :success, :kind => "LinkedIn") if is_navigational_format?
else
session["devise.linkedin_data"] = request.env["omniauth.auth"]
redirect_to root_path
end
end
My admin_mailer has:
def new_user_waiting_for_approval(user)
#user = user
mail(to: "myemailaddress#gmail.com", from: "myemailaddress#gmail.com",
subject: "Registration Request #{user.first_name} #{user.last_name} <#{user.email}>")
end
def new_user_waiting_for_access(user)
#user = user
mail(to: user.email, from: "myemailaddress#gmail.com", subject: "Welcome to Co #{user.first_name}")
end
I'm wondering whether I need to replace user with current_user to make use of the devise method or maybe whether some variation on {} and/or "" is required around the user.email in the second method?? I've tried a few different variations and combinations but haven't had any success.
Thank you for your help.
def send_user_welcome_mail
AdminMailer.new_user_waiting_for_access(user).deliver
end
should be replaced with
def send_user_welcome_mail
AdminMailer.new_user_waiting_for_access(self).deliver
end
user -> self

How to redirect a user signed up with omniauth (Rails with Devise) to a specific page?

Hi I just setup omniauth for Facebook and Google in my app by following this tutorial : http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/
Here's my OmniauthCallbacksController :
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
#user = User.find_for_oauth(env["omniauth.auth"], current_user)
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".gsub(/_/," ").split[0...1].join(' ').capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:google_oauth2, :facebook].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
#if resource.email_verified?
super resource
#else
# finish_signup_path(resource)
#end
end
# def google_oauth2
# raise request.env["omniauth.auth"]
# end
end
I want to redirect all the users who have signed up with facebook or google (Not sign in, sign up for a new account) to their user profile page with a notice asking them to change their username because I set the email as their username on signup. How can I do this?
after this line sign_in_and_redirect #user, event: :authentication
You can add a cookies value that this user is signed up using omniauth.
cookies[:oA] = true
In the after_sign_in_path_for(resource) method check if the value of the cookie is true, add a path username_path(resource) for example.

redirect omniauth-facebook to a specific page after authentication

Newbie here , i have omniauth-facebook setup in an application , every thing working fine , my only issue i want to redirect to another page after the authentication ,but i can't quite figure it out .
my first solution was to add a route to match the auth/facebook/callback to "sessions#new " it's not working . other thing i try is to add a redirect in the controller , not working also , what is the proper to redirect to a specific page ?
controller
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
sign_in_and_redirect , :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "sign in successfuly") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
routes
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
thanks for any help .
When your get user by find_for_facebook_oauth method then you can login with that user and use redirect_to for your desired path. You can do something like:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
sign_in(#user)
redirect_to desired_path, notice: 'Signed in successfully.'
set_flash_message(:notice, :success, :kind => "sign in successfuly") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end

Resources