I'm trying to implement facebook login authentication using devise and omniauth, but I got an error during the callback section.
The error goes like this...
> `User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."provider" = ? AND "users"."uid" = ? ORDER BY "users"."id" ASC LIMIT 1 [["provider", "facebook"], ["uid", "1517802078458724"]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 411ms
NameError (undefined local variable or method `user' for #<User:0x007f3008b8a760>):
app/models/user.rb:34:in `password_required?'
app/models/user.rb:18:in `block in from_omniauth'
app/models/user.rb:12:in `tap'
app/models/user.rb:12:in `from_omniauth'
app/controllers/omniauth_callbacks_controller.rb:4:in `all'`
It seems like things work until /auth/facebook/ and then it goes up to the part where retrieving uid and provider ends.
My code in controllers, model and routes are as follows..
For callbacks controller and application controller
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
sign_in_and_redirect user, notice: "Signed in!"
else
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
alias_method :facebook, :all
end
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
My user.rb model
class User < ActiveRecord::Base
has_many :authentications
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :omniauthable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauth_providers => [:facebook]
attr_accessible :email, :password, :password_confirmation
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
def self.new_with_sessions(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
end
def password_required?
super && user.blank?
end
end
My schema.rb
ActiveRecord::Schema.define(version: 20141120211712) do
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "provider"
t.string "uid"
t.string "name"
t.string "oauth_token"
t.datetime "oauth_expires_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
My routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks" }
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
and finally my gemfile
source 'https://rubygems.org'
ruby '2.1.4'
gem 'rails', '4.2.0.beta4'
gem 'bcrypt', '3.1.7'
gem 'faker', '1.4.2'
gem 'carrierwave', '0.10.0'
gem 'mini_magick', '3.8.0'
gem 'fog', '1.23.0'
gem 'will_paginate', '3.0.7'
gem 'bootstrap-will_paginate', '0.0.10'
gem 'bootstrap-sass', '3.2.0.0'
gem 'sass-rails', '5.0.0.beta1'
gem 'uglifier', '2.5.3'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '4.0.0.beta2'
gem 'turbolinks', '2.3.0'
gem 'jbuilder', '2.2.3'
gem 'rails-html-sanitizer', '1.0.1'
gem 'sdoc', '0.4.0', group: :doc
gem 'devise', github: 'plataformatec/devise'
gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
gem 'omniauth-linkedin'
gem 'figaro'
gem 'protected_attributes'
I would really like this feature of facebook login in my app... Thank you very much in advance. I would greatly appreciate any input..
The problem is in the
password_required?
which is called when the user is saved.Its trying to test whether the
user
is blank? However the user variable/method does not exist in its scope. Instead you need to useself
which refers to the current instance of User.So the line should be:
or just: