User not being added to database with Devise Omniauth Facebook - ruby-on-rails

I have Devise user auth included in my site and it is working well. I'm now trying to add Facebook authentication.
I'm able to login with FB, and the user is redirected back to my site ok. When I check the connected apps in FB settings I can see my site is there listed.
The problem is that the FB is not added to my user table. When I check the db, the provider and uid fields are blank, and site is still asking for the user to sign in.
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :validatable,
has_many :comments
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
#user.image = auth.info.image # assuming the user model has an image
# If you are using confirmable and the provider(s) you use validate emails,
# uncomment the line below to skip the confirmation emails.
user.skip_confirmation!
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Callback 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.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
def failure
redirect_to root_path
end
routes.rb
#authentication
devise_for :users, path: "auth", controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
unlocks: 'users/unlocks',
omniauth_callbacks: 'users/omniauth_callbacks'
}
User Session Controller
class Users::SessionsController < Devise::SessionsController
respond_to :js
before_action :configure_permitted_parameters, :if => :devise_controller?
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_in_params
devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
end
end
devise.rb
config.omniauth :facebook, '******', '*************', scope: "email", info_fields: 'email'
Update
Just caught the fact I have fname and lname fields in my user table, so have adjusted user.rb to reflect that:
user.fname = auth.info.fname

Related

Invalid App ID facebook, Omniauth rails 5.2.4

When I sign in my app with facebook I am getting the error "Invalid App ID" even I verified my app id and it is correct.
what am I doing wrong in my code?
Here is my code:
devise.rb
config.omniauth :facebook, 'xxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxx', token_params: { parse: :json }
omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :developer unless Rails.env.production?
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
end
routes.rb
Rails.application.routes.draw do
root to: 'surveys#index'
resources :surveys
devise_for :users, controllers: {
sessions: 'users/sessions',
confirmations: 'confirmations',
omniauth_callbacks: "users/omniauth_callbacks"
}
end
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 #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
def failure
redirect_to root_path
end
end
user.rb
class User < ApplicationRecord
has_many :surveys
mount_uploader :avatar, AvatarUploader
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable,
:omniauthable, omniauth_providers: %i[facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0, 20]
user.first_name = auth.info.first_name # assuming the user model has a name
# If you are using confirmable and the provider(s) you use validate emails,
# uncomment the line below to skip the confirmation emails.
user.skip_confirmation!
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Thanks in advance
I think you are configuring omniauth two times. You should remove omniauth.rb under config/initializers folder.
Remember that config.omniauth adds omniauth provider middleware to your application. This means you should not add this provider middleware again in config/initializers/omniauth.rb as they'll clash with each other and result in always-failing authentication.
Check Devise wiki on Facebook omniauth for Facebook integration.

Cant get current_user Device and oAuth facebook

I am signing in users only from facebook with Omniauth
** Users::OmniauthCallbackController**
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?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to games_path
end
end
but when i try to get current_user to another contoller it always returns nil.
I have read that devise has a built in function for current_user but that didn t seem to work properly(also returned nil every single time) so i implemented another method.
current_user helper
before_action :define_current_user
def current_user
User.find_by id: session["current_user_id"]
end
helper_method :current_user
How can i make it work?
User.rb
class User < ApplicationRecord
belongs_to :team
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :rememberable, :trackable,:validatable
,:omniauthable, :omniauth_providers => [:facebook]
def self.new_with_session(params,session)
super.tap do |user|
if data = session["devise.facebook_data"] &&
session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
#Saving new user to the database
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do|user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name
user.image = auth.info.avatar
user.save!
end
end
end
Don't forget to add before_action :authenticate_user! callback to needed controllers. In this case you'll be able to get value of default current_user from Devise

Why is my omniauth-github not working with devise?

I have a rails app and I want to make a Github connect. I have followed the devise tutorial about Facebook and adapted it for Github.
I have this error on the callback, when accessing /users/auth/github/callback?code=xxxxxxx
ActionController::RoutingError (uninitialized constant Users):
I know that other posts are related to this issue but their answer do not fix my problem.
routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def github
# 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 => "Github") if is_navigational_format?
else
session["devise.github_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
end
models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:github]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.github_data"] && session["devise.github_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end

Devise omniauth-facebook redirect_uri Url must absolute

My Rails app when I tried to integrate gem "omniauth-facebook" with devise, I receive the following error on facebook: The redirect_uri URL must be absolute.
Following were my config
devise.rb
config.omniauth :facebook, "ID", "SECRET",callback_url: "/auth/facebook"
My user.rb model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
end
end
end
My routes:
devise_for :users, :controllers => {:omniauth_callbacks => "users/omniauth_callbacks"}
And Controller OmniauthCallbacksController
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.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
def failure
redirect_to root_path
end
end
What am I missing here?
Adding
:client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}
To config.omniauth in the initializer solved the issue for me.
I also configured the path to be absolute like so:
callback_url: ENV['SERVER_ROOT']+'/users/auth/facebook/callback'

Devise doesn't login when a session already exists

I'm having a little problem with Devise. When I try to login with an account, while I'm logged in with a different account, Devise is persisting the session of the first account I logged in with.
This happens when I log with via omniauth first, then try to log in manually with Devise.
here is my omniauth_controller
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
respond_to :json
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"]) if request.env["omniauth.auth"].present?
if #user && #user.persisted?
sign_in #user
cookies[:uId] = #user.id
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
end
redirect_to root_url
end
end
my user.rb file:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
This is because of the way devise is storing the data in your session. When you login manually it is storing the user_id versus when you use omniauth it stores other data in the session to know how to authenticate.
You can manually clear it out when the user visits the sign in/out pages:
class SessionsController < ApplicationController
before_action :clear_devise_session, only: [:new, :destroy]
private
def clear_devise_session
session['devise.facebook_data'] = nil
end
end
Granted it is recommended that a GET request should never manipulate state you may not want to do this on the new action and only the destroy action.
If this is just to test when developing you can run rake db:sessions:clear.

Resources