users.rb devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable #...field setups for devise... # ## Provide foundation to support multiple omniauth providers # embeds_many :authentications field :name, :type => String field :provider, :type => String # TODO: This is a complete hack, better way? validates_uniqueness_of :email attr_accessible :name, :email, :password, :password_confirmation, :remember_me index( { email: 1}, { background: true, unique: true } ) index( { "authentications.provider" => 1 }, { background: true } ) index( { "authentications.uid" => 1 }, { background: true } ) def self.new_with_session(params, session) # ## When omniauth is generating the user data this method is requested # if session["devise.user_attributes"] auth = session["devise.user_attributes"] new do |user| user.name = auth['info']['name'] unless auth['info']['name'].blank? user.name ||= auth['info']['nickname'] unless auth['info']['nickname'].blank? user.name ||=auth['info']['first_name'] + ' ' + auth['info']['last_name'] unless auth['info']['first_name'].blank? || auth['info']['last_name'].blank? user.email = auth['info']['email'] unless auth['info']['email'].blank? user.provider = auth['provider'] # ## This password stuff is a complete hack # user.password, user.password_confirmation = auth['credentials']['token'] user.valid? end else # ## We don't have a omniauth hash, so default to normal devise registration # super end end def password_required? super && provider.blank? end def update_with_password(params, *options) if encrypted_password.blank? update_attributes(params, *options) else super end end Authentication.rb class Authentication include Mongoid::Document field :provider, :type => String, :default => '' field :uid, :type => String, :default => '' embedded_in :user # ## TODO: At the least, we'll want to add in data hooks for FB ## for posting to user's wall, events, etc. # end authentication_controller.rb class AuthenticationController < Devise::OmniauthCallbacksController def all auth = request.env['omniauth.auth'] authentication = User.first.authentications.where(:provider => auth['provider'], :uid => auth['uid']).first if current_user # ## we've got a logged in user, lets see if they have already linked their account # if current_user.authentications.where(:provider => auth['provider'], :uid => auth['uid']) flash.notice = "#{auth['provider']} is already linked to your account." redirect_to '/' else current_user.authentications.create!(:provider => auth['provider'], :uid => auth['uid']) flash.notice = "Sucessfully linked your #{auth['provider']} to your account!" sign_in_and_redirect current_user #TODO: think about redirection end elsif authentication # ## We don't have a currently logged in user but we do have this provider and uid # flash.notice = "Signed in via your #{auth['provider']} account!" sign_in_and_redirect(:user, authentication.user) elsif user = create_new_omniauth_user(auth) user.authentications.create!(:provider => auth['provider'], :uid => auth['uid']) flash.notice = "Sucessfully created account!" sign_in_and_redirect user #TODO: think about redirection else session["devise.user_attributes"] = auth redirect_to new_user_registration_url end end alias_method :facebook, :all # def destroy # @authentication = current_user.authentications.find(params[:id]) # @authentication.destroy # flash.notice = "Successfully destroyed authenication!" # redirect_to root # end def create_new_omniauth_user(auth) user = User.new_with_session(auth, session) if user.save user else nil end end end In routes.rb I changed the controllers: {omniauth_callbacks: "omnitauth_callback"} to controllers: {omniauth_callbacks: "authentication"}