Invalid App ID facebook, Omniauth rails 5.2.4 - ruby-on-rails

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.

Related

User not being added to database with Devise Omniauth Facebook

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

Rails devise omniauth facebook

I can't get devise omniauth-facebook to work. I've followed the devise guide to no avail. I think my problem is the model is not retrieving info.
Model
class User < ActiveRecord::Base
has_attached_file :image, styles: {large: "1920x1080#", medium: "800x500#", thumb: "100x100"}, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
# 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 admin?
admin
end
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
puts request.env["omniauth.auth"]
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
Routes.rb
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users do
delete 'logout' => 'sessions#destroy', :as => :destroy_user_session,
:controllers => { :omniauth_callbacks => "user/omniauth_callbacks" }
end
Controller
class User::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# You should configure your model like this:
# devise :omniauthable, omniauth_providers: [:twitter]
# You should also create an action method in this controller like this:
# def twitter
# end
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 self.new_with_session(params, session)
if session["devise.user_attributes"]
new(session[devise.user_attributes], without_protection: true) do |user|
user.attributes = params
user.valid?
end
else
super
end
After I click "Login with facebook", it directs to a facebook url, I input a password, press enter, get redirected to the same page with a long url. (http://localhost:3000/demographics?code=AQDK1z40APoLiWykomxDDUljBUNHotenM4lzj_bZMhH8iQ74J_Nu_EUnPqBqkbNAeWQEPZwQs7YghqkB4eD7AoQLkN_RuYIlmotMtrJc4UyGRSe3CJIHcxp6kcB9BuYHA_Ldz0NMJvvGzOuvC-uDpFn6TyrzvV5v9LvivORXVduSsCy7_r6PcW8jxAkWqZzKyASXf26h8h3f_kha2d0KX6Ygft8ozN1HT9Xr-1y7ZtIKgTXEGMrqK950kASv2oTE0tQ5CYt6mfEZsVyLpykYIApOls8NLhjOaOIJewzV9EnLdSq0FbrvtedhhDmy-hg6IkRAbRVgwEkfUFsi9DXoxKyX&state=bdbf498f33f67ef57f3f54b846f870f21bb80c039c099f1a#=)
EDIT:
Now I am getting
Could not authenticate you from Facebook because "Invalid credentials".
So the problem was I didn't config the routes properly.
In fact, I had to remove all existing devise routes and add this line.
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
This is what worked for me:
user model
devise :omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.username = auth.info.name #gives full user name
user.password = Devise.friendly_token[0,20]
user.skip_confirmation!
user.save
end
end
devise.rb
config.omniauth :facebook, ENV['facebook_key'], ENV['facebook_secret'],
scope: 'email,public_profile', info_fields: 'email, first_name, last_name'
callbacks_controller.rb
class CallbacksController < ApplicationController
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication
flash[:notice] = "Logged in as #{#user.username}"
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
routes.rb
devise_for :users, controllers: { omniauth_callbacks: "callbacks" }
The problem is Facebook is not always returning email for user
from facebook developers https://developers.facebook.com/bugs/298946933534016
Some possible reasons:
No Email address on account
No confirmed email address on account
No verified email address on account
User entered a security checkpoint which required them to reconfirm
their email address and they have not yet done so
Users's email address is unreachable
Set an condition in your controller if request.env["omniauth.auth"].info.email.present? see the script below.
class User::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
puts request.env["omniauth.auth"] # check if request.env["omniauth.auth"] is provided an email
if request.env["omniauth.auth"].info.email.present?
#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
else
redirect_to new_user_registration_url, notice: "Couldn't connect to your #{request.env["omniauth.auth"].provider} account. Try to sign up."
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'

omniauth.auth for Facebook not returning full hash and not able to successfully login with facebook

I'm working on the facebook clone project from http://www.theodinproject.com/ruby-on-rails/final-project.
I'm stuck with the omniauth-facebook portion, and I'm not able to successfully login with facebook. I think the problem might be due to the request.env["omniauth.auth"]. When I try to raise request.env["omniauth.auth"].to_yaml. I get the following incomplete hash. It's missing a lot of information such as first_name, last_name, gender, etc.
--- !ruby/hash:OmniAuth::AuthHash
provider: facebook
uid: '10206926404981253'
info: !ruby/hash:OmniAuth::AuthHash::InfoHash
name: Thomas Pan
image: http://graph.facebook.com/10206926404981253/picture
credentials: !ruby/hash:OmniAuth::AuthHash
token: <token>
expires_at: 1442277104
expires: true
extra: !ruby/hash:OmniAuth::AuthHash
raw_info: !ruby/hash:OmniAuth::AuthHash
name: Thomas Pan
id: <id>
** Replaced some info with <> for security.
I'm using this along with devise as well.
Everything else seems to be set up correctly as I've followed the instructions here for devise and omniauth-facebook. https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
user.rb
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.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.gender = auth.extra.raw.gender
end
end
devise.rb
config.omniauth :facebook, ENV['FB_APP_ID'], ENV['FB_APP_SECRET']
routes.rb
devise_for :users, :controllers => { :registrations => "users/registrations", :omniauth_callbacks => "users/omniauth-callbacks" }
omniauth_callbacks_controller.rb
def facebook
raise request.env['omniauth.auth'].to_yaml
end
end
Any assistance would be greatly appreciated!
Version info:
Rails 4.2.1
Ruby 2.0.0
In devise.rb:
config.omniauth :facebook, ENV['FB_APP_ID'], ENV['FB_APP_SECRET'], scope: 'email', info_fields: 'email,name,first_name,last_name,gender'
Create a OmniauthCallbacksController and Add the following code
class OmniauthCallbacksController < ApplicationController
skip_before_filter :authenticate_user!
def all
p env["omniauth.auth"]
user = User.from_omniauth(env["omniauth.auth"])
if user.persisted?
# flash[:alert] = "You have to confirm your account before continuing."
sign_in_and_redirect(user)
else
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
def failure
#handle you logic here..
#and delegate to super.
redirect_to new_user_registration_url
end
alias_method :facebook, :all
end
In your config/routes.rb
devise_for :users, controllers: { omniauth_callbacks: "omniauth_callbacks" }
Create a Authorization model
rails g model Authorization
In migration add following code
class CreateAuthorizations < ActiveRecord::Migration
def change
create_table :authorizations do |t|
t.string :provider
t.string :uid
t.integer :user_id
t.string :token
t.string :secret
t.timestamps
end
end
end
then
rake db:migrate
In your models/authorization.rb
belongs_to :user
In your models/user.rb
has_many :authorizations
def self.from_omniauth(auth)
authorization = Authorization.where(:provider => auth.provider, :uid => auth.uid.to_s).first_or_initialize
authorization.token = auth.credentials.token
if authorization.user.blank?
user = User.where('email = ?', auth["info"]["email"]).first
if user.blank?
user = User.new
user.password = Devise.friendly_token[0,10]
user.email = auth.info.email
user.save
end
authorization.user_id = user.id
end
authorization.save
authorization.user
end
Hope this will help you.

Devise + OmniAuth Instagram: Not found. Authentication passthru

So I've found similar questions on this site with not a really direct solution to this problem that I'm seeing.
I'm using omniauth-instagram and omniauth-facebook with devise and getting the error below (with both providers).
URL:
http://localhost:3000/users/auth/callbacks/facebook
Error: Not found. Authentication passthru.
Below are examples of my callbacks_controller.rb, user.rb and routes.rb -- Any helpful tips in the right direction are much appreciated. Let me know if I should provide any other information!
callbacks_controller.rb
class Users::Auth::CallbacksController < Devise::OmniauthCallbacksController
def instagram
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_oauth(request.env["omniauth.auth"], current_users)
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Instagram") if is_navigational_format?
else
session["devise.instagram_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_oauth(request.env["omniauth.auth"], current_users)
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
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
devise :omniauthable, :omniauth_providers => [:instagram, :facebook]
def self.find_for_oauth(auth, signed_in_resource = nil)
# Get the identity and user if they exist
identity = Identity.find_for_oauth(auth)
user = identity.user
if user.nil?
# Get the existing user from email if the OAuth provider gives us an email
user = User.where(:email => auth.info.email).first if auth.info.email
# Create the user if it is a new registration
if user.nil?
user = User.new(
name: auth.extra.raw_info.name,
#username: auth.info.nickname || auth.uid,
email: auth.info.email.blank? ? TEMP_EMAIL : auth.info.email,
password: Devise.friendly_token[0,20]
)
user.skip_confirmation!
user.save!
end
# Associate the identity with the user if not already
if identity.user != user
identity.user = user
identity.save!
end
end
user
end
end
routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "users/auth/callbacks" }
Did you add both in devise.rb?
# devise.rb
# ...
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
config.omniauth :facebook, "KEY", "SECRET"
config.omniauth :instagram, "KEY", "SECRET"
After configuring your strategy, you need to make your model (e.g. app/models/user.rb) omniauthable:
devise :omniauthable, :omniauth_providers => [:facebook, :instagram]

Resources