-
-
Save despo/11129786 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
# ==> Configuration for any authentication mechanism | |
# Configure which keys are used when authenticating a user. The default is | |
# just :email. You can configure it to use [:username, :subdomain], so for | |
# authenticating a user, both parameters are required. Remember that those | |
# parameters are used only when authenticating and not when retrieving from | |
# session. If you need permissions, you should implement that in a before filter. | |
# You can also supply a hash where the value is a boolean determining whether | |
# or not authentication should be aborted when the value is not present. | |
config.authentication_keys = [ :login ] | |
... | |
# ==> OmniAuth | |
# Add a new OmniAuth provider. Check the wiki for more information on setting | |
# up on your models and hooks. | |
#config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' | |
config.omniauth :twitter, 'yourid', 'yoursecret', {:client_options => {:ssl => {:ca_path => '/etc/ssl/certs'}}} | |
if Rails.env == "production" | |
config.omniauth :facebook, 'yourid', 'yoursecret', {:client_options => {:ssl => {:ca_path => '/etc/ssl/certs'}}} | |
else | |
config.omniauth :facebook, 'yourid', 'yoursecret', {:client_options => {:ssl => {:ca_path => '/etc/ssl/certs'}}} | |
end | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
... | |
has_many :authentications, :dependent => :destroy | |
# Include default devise modules. Others available are: | |
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable | |
devise :database_authenticatable, :registerable, | |
:recoverable, :rememberable, :trackable, :validatable, :omniauthable | |
#:confirmable, :lockable | |
# Allow people to log in with username (from oauth provider) or email | |
attr_accessor :login | |
# Setup accessible (or protected) attributes for your model | |
attr_accessible :login, :email, :name, :password, :password_confirmation, :remember_me | |
def password_required? | |
(authentications.empty? || !password.blank?) && super | |
end | |
def self.new_with_session(params, session) | |
super.tap do |user| | |
if data = session["devise.facebook_data"] | |
user.email = data["email"] | |
end | |
end | |
end | |
#Override Devise's update with password to allow registration edits without password entry | |
def update_with_password(params={}) | |
params.delete(:current_password) | |
self.update_without_password(params) | |
end | |
# Update user record and create or update authentication record | |
def set_token_from_hash(auth_hash, user_hash) | |
self.update_attribute(:name, user_hash[:name]) if self.name.blank? | |
self.update_attribute(:email, user_hash[:email]) if self.email.blank? | |
token = self.authentications.find_or_initialize_by_provider_and_uid(auth_hash[:provider], auth_hash[:uid]) | |
token.update_attributes( | |
:name => auth_hash[:name], | |
:link => auth_hash[:link], | |
:token => auth_hash[:token], | |
:secret => auth_hash[:secret] | |
) | |
end | |
protected | |
# From Devise docs to allow name or email as login | |
def self.find_for_database_authentication(warden_conditions) | |
conditions = warden_conditions.dup | |
login = conditions.delete(:login) | |
where(conditions).where(["lower(name) = :value OR lower(email) = :value", { :value => login.downcase }]).first | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController | |
def facebook | |
oauthorize "Facebook" | |
end | |
def twitter | |
oauthorize "Twitter" | |
end | |
def passthru | |
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false | |
end | |
private | |
def oauthorize(kind) | |
omniauth = request.env['omniauth.auth'] | |
@user = User.includes(:authentications).merge(Authentication.where(:provider => omniauth['provider'], :uid => omniauth['uid'])).first | |
if @user # if user exists and has used this authentication before, update details and sign in | |
@user.set_token_from_hash(provider_auth_hash(kind, omniauth), provider_user_hash(kind, omniauth)) | |
sign_in_and_redirect @user, :event => :authentication | |
elsif current_user # if user exists then new authentication is being added - so update details and redirect to | |
current_user.set_token_from_hash(provider_auth_hash(kind, omniauth), provider_user_hash(kind, omniauth)) | |
redirect_to edit_user_registration_url | |
else # create new user and new authentication | |
user = User.new | |
user.password = Devise.friendly_token[0,20] | |
user.authentications.build(provider_auth_hash(kind, omniauth)) | |
if user.save :validate => false # validate false handles cases where email not provided - such as Twitter | |
sign_in_and_redirect(:user, user) | |
else # validate false above makes it almost impossible to get here | |
session["devise.#{kind.downcase}_data"] = provider_auth_hash(kind,omniauth).merge(provider_user_hash(kind,omniauth)) | |
redirect_to new_user_registration_url | |
end | |
end | |
end | |
def provider_auth_hash(provider, hash) | |
# Create provider specific hash's to populate authentication record | |
case provider | |
when "Facebook" | |
{ | |
:provider => hash['provider'], | |
:uid => hash['uid'], | |
:name => hash['extra']['user_hash']['name'], | |
:link => hash['extra']['user_hash']['link'], | |
:token => hash['credentials']['token'], | |
:secret => nil | |
} | |
when "Twitter" | |
{ | |
:provider => hash['provider'], | |
:uid => hash['uid'], | |
:name => hash['user_info']['nickname'], | |
:link => hash['user_info']['urls']['Twitter'], | |
:token => hash['credentials']['token'], | |
:secret => hash['credentials']['secret'] | |
} | |
end | |
end | |
def provider_user_hash(provider, hash) | |
# Create provider specific hash's to populate user record if appropriate | |
case provider | |
when "Facebook" | |
{ | |
:name => hash['extra']['user_hash']['name'], | |
:email => hash['extra']['user_hash']['email'] | |
} | |
when "Twitter" | |
{ | |
:name => hash['user_info']['name'] | |
} | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment