I've spent the last day trying to fix this issue and it's driving me nuts.
Last night, I had facebook login working on my site and was retrieving basic user info. My problems started when I added :scope => 'user_birthday'
to config/initializers/omniauth.rb
which now looks like this
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, "APP_ID", "APP_SECRET", :scope => 'user_birthday'
end
For reference, I've removed the line config.omniauth :facebook, "APP_ID", "APP_SECRET"
from config/initializers/devise.rb
I spent hours trying to get this to work but had to give up eventually. Then this morning I ran it again and it worked. Overjoyed, I tried to add another parameter to :scope
but now the whole thing is broken again. I can get it to work if I remove the :scope
but when I put it back in it fails every time (even if it's just :scope => 'user_birthday'
like I had working first thing this morning).
To locate the problem, I put debug code in omniauth_callbacks_controller.rb
and it now looks 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.from_omniauth(request.env["omniauth.auth"])
puts "start before persist debug"
puts @user.birthday
puts @user.persisted?
puts "end before persist debug"
if @user.persisted?
puts "Start persisted debug"
puts request.env["omniauth.auth"]
puts "End debug"
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"]
puts "Start unpersisted debug"
puts request.env["omniauth.auth"]
puts "End debug"
redirect_to new_user_registration_url
end
end
end
This debug clearly shows that facebook is returning the necessary information but the app is failing because .persisted?
is returning false and so I get re-directed to the new_user_registration page which returns the following:-
NoMethodError in Devise::Registrations#new
Showing /home/action/workspace/cloudapp/app/views/devise/shared/_links.html.erb where line #23 raised:
undefined method `omniauth_authorize_path' for #<#<Class:0x007f3aeffff038>:0x007f3aefffdf08>
I can't for the life of me figure out why .persisted?
is returning false. I'm using Nitrous.io for development with a Heroku postgresql database. I've confirmed there are no users in the database by running
rails c
User.all
This returns:
User Load (89.4ms) SELECT "users".* FROM "users"
=> #<ActiveRecord::Relation []>
I have a feeling the problem is in models/user.rb
but I can't figure out how to debug it to see if it's finding a user and therefore not persisting or trying to create one and failing. Does anyone know a simple way to debug this?
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.birthday = auth.extra.raw_info.birthday
# user.image = auth.info.image # assuming the user model has an image
end
end
I've gone over everything about 50 times and am close to giving up.
The only thing I can think of is that where(provider: auth.provider, uid: auth.uid)
is returning something (which it shouldn't because my database is empty). Would there possibly be an index that exists somewhere outside my database and that's what it's searching?
Please, for my sanity, can anyone help? If you need more info I'll gladly provide it
Edit 1
Just tried the following and it works which make me more confused than ever:
:scope => 'user_birthday'
left in. Facebook lists the permissions sought as your public profile and birthday
. Accept and get sent back to my site which fails as per above (even though the info is definitely being sent back):scope => 'user_birthday'
and try log in using facebook again. Get directed to facebook which lists permission sought as your public profile and email address
. Accept and get directed back to site which now works and also has the user birthday stored and accessible because I had the permisision from facebook from number 2 above.I'm completely at a loss now
To find out about why is the object not being saved. You need to puts the errors.
puts @user.errors.to_a
And to check the content of the auth
puts request.env["omniauth.auth"]