public
Last active

Extend http://railscasts.com/episodes/235-devise-and-omniauth-revised to support scenario where a user first creates account without Facebook login, then later authenticates with Facebook.

  • Download Gist
omniauth_callbacks_controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
# app/controllers/omniauth_callbacks_controller.rb
 
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
user = User.from_omniauth(request.env["omniauth.auth"])
if user.has_password? && user.facebook_uid_was.nil? && user != current_user
session["omniauth.user_attributes"] = user.attributes
redirect_to user_omniauth_link_url
elsif user.save
flash.notice = "You have been signed in"
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
 
# GET /users/auth/link
def link_user
load_user_from_session
render 'devise/omniauth/link_user'
end
 
# PUT /users/auth/link
def create_link_user
load_user_from_session
if @user.valid_password?(params[:user][:password])
@user.update_attributes(session["omniauth.user_attributes"])
@user.save!
session["omniauth.user_attributes"] = nil
flash.notice = "Signed in!"
sign_in_and_redirect @user
else
@user.errors[:base] << "Password invalid"
render 'devise/omniauth/link_user'
end
end
 
private
def load_user_from_session
email = session["omniauth.user_attributes"]["email"]
@user = User.where(:email => email).first
raise AbstractController::RecordNotFound unless @user
end
end
routes.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# config/routes.rb
 
# ...
 
devise_for :users,
path_names: { sign_in: "login", sign_out: "logout" },
controllers: { registrations: 'registrations', omniauth_callbacks: 'omniauth_callbacks' }
 
devise_scope :user do
get "/users/auth/link" => "omniauth_callbacks#link_user", :as => :user_omniauth_link
put "/users/auth/link" => "omniauth_callbacks#create_link_user"
end
 
# ...
user.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# app/models/user.rb
 
class User < ActiveRecord::Base
 
class InvalidPassword < Exception ; end
 
def self.from_omniauth(omniauth)
user = where(:provider => omniauth.provider, :uid => omniauth.uid).first || where(:email => omniauth.info.email).first || new
user.uid = omniauth.uid
user.provider = omniauth.provider
user.email = omniauth.info.email if user.email.blank?
user.oauth_token = omniauth.credentials.token
user.oauth_expires_at = Time.at(omniauth.credentials.expires_at)
user
end
 
def has_password?
! encrypted_password.blank?
end
 
# ...
 
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.