ruby-on-railsdeviseomniauthomniauth-facebook

Rails devise omniauth-facebook .persisted? returning false


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:

  1. Delete the app from my facebook account as I'm testing using that account
  2. Try to log in with facebook with :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)
  3. Remove :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


Solution

  • 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"]