Nel vostro caso specifico si può pensare che meditano consente all'applicazione di autenticare gli utenti utilizzando un modulo (es: utilizzando una e-mail e password) o un token di autenticazione, Omniauth consente alla tua applicazione di "parlare" ai server di Facebook per autenticare un utente. In altre parole, Omniauth si trova in cima a Devise e estende il numero di modi in cui l'utente può autenticarsi.
Per implementare Facebook Login è necessario:
0) configurare devise: basta seguire questo: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
1) esporre un link nella vista che se cliccato dall'utente dirà Omniauth per iniziare " parlando "al server di Facebook.
=link_to image_tag("facebook_64.png", :size => "64x64", :alt => "Facebook"), user_omniauth_authorize_path(:facebook, :display=>"dialog"), :title=>"Facebook"
2) A un certo punto il server di Facebook vi chiamerà applicazione in modo da avere per implementare un controller di rispondere a Facebook
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
before_filter { @omniauth_hash = env["omniauth.auth"] }
# This method is responsible to create a registration_hash given an
# omniaauth_hash
# schama: https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
def self.build_registration_hash(omniauth_hash={})
if (omniauth_hash["provider"].downcase.eql?("facebook"))
provider = "facebook"
# catch any excpetions thrown by code just to make sure we can continue even if parts of the omnia_has are missing
begin
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
sex = omniauth_hash.fetch('extra', {}).fetch('user_hash',{})['gender']
birthday = Date.strptime(omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday'],'%m/%d/%Y') if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['birthday']
if omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone']
utc_offset_in_hours = (omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['timezone']).to_i
time_zone = (ActiveSupport::TimeZone[utc_offset_in_hours]).name
else
time_zone = nil
end
locale = omniauth_hash.fetch('extra', {}).fetch('user_hash', {})['locale']
home_town = omniauth_hash.fetch('extra', {}).fetch('user_hash', {}).fetch('location', {})['name']
if omniauth_hash.fetch('user_info', {})['image']
photo_url = (omniauth_hash.fetch('user_info', {})['image']).gsub("=square","=large") #http://graph.facebook.com/531564247/picture?type=square
else
photo_url = nil
end
rescue => ex
logger.error("Error while parsing facebook auth hash: #{ex.class}: #{ex.message}")
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
end
elsif omniauth_hash['uid'].downcase.include?("google.com")
provider = "google"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
elsif omniauth_hash['uid'].downcase.include?("yahoo.com")
provider = "yahoo"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
elsif omniauth_hash['uid'].downcase.include?("aol.com")
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
provider = "aol"
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
else
provider = "open_id"
if omniauth_hash['user_info']['first_name'] and omniauth_hash['user_info']['last_name']
first_name = omniauth_hash['user_info']['first_name']
last_name = omniauth_hash['user_info']['last_name']
elsif omniauth_hash['user_info']['name']
first_name = omniauth_hash['user_info']['name'].split(' ')[0]
last_name = omniauth_hash['user_info']['name'].split(' ')[1]
else
first_name = nil
last_name = nil
end
sex = nil
birthday = nil
time_zone = nil
locale = nil
home_town = nil
photo_url = nil
end
h = {
:provider => provider,
:email => omniauth_hash['user_info']['email'],
:profile_attributes => {
:first_name => first_name ,
:last_name => last_name,
:avatar_url => photo_url,
:sex => sex,
:birthday => birthday,
:time_zone => time_zone,
:locale => locale,
:location => home_town
}
}
end
def process_callback
# The registration hash isolates the rest of the code from learning all the different structures
# of the omnia_hash
registration_hash = Users::OmniauthCallbacksController.build_registration_hash(@omniauth_hash)
logger.debug(registration_hash.to_yaml)
# Set the @user to nil
@user = nil
# Find if an authentication token for this provider and user id already exists
authentication = Authentication.find_by_provider_and_uid(@omniauth_hash['provider'], @omniauth_hash['uid'])
if authentication # We found an authentication
if user_signed_in? && (authentication.user.id != current_user.id)
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.account_already_taken",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
redirect_to edit_user_account_path(current_user)
return
end
else
# We could not find the authentication than create one
authentication = Authentication.new(:provider => @omniauth_hash['provider'], :uid => @omniauth_hash['uid'])
if user_signed_in?
authentication.user = current_user
else
registration_hash[:skip_confirmation] = true
authentication.user = User.find_by_email(registration_hash[:email]) || User.create_user(registration_hash)
end
end
@user = authentication.user
# save the authentication
authentication.token = @omniauth_hash
authentication.provider_name = registration_hash[:provider]
authentication.provider_username = registration_hash[:email]
if !authentication.save
logger.error(authentication.errors)
end
# If a user is signed in then he is trying to link a new account
if user_signed_in?
if authentication.persisted? # This was a linking operation so send back the user to the account edit page
flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.link_account",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
else
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.link_account",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email],
:errors =>authentication.errors
end
redirect_to edit_user_account_path(current_user)
else
# This was a sign in operation so sign in the user and redirect it to his home page
if @user.persisted? && authentication.persisted?
flash[:success] = I18n.t "controllers.omniauth_callbacks.process_callback.success.sign_in",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
sign_in_and_redirect(:user,@user)
else
session['registration_hash'] = registration_hash
flash[:error] = I18n.t "controllers.omniauth_callbacks.process_callback.error.sign_in",
:provider => registration_hash[:provider].capitalize,
:account => registration_hash[:email]
redirect_to new_registration_users_url
end
end
end
def facebook
process_callback
end
def gmail
process_callback
end
Ora si noterà che io chiamo un User.create_user (registration_hash). Questa implementazione del metodo dipenderà da come la vostra applicazione creare un utente, ma al minimo il metodo deve creare un utente e assegnare una password casuale:
def self.create_user(registration_hash)
logger.info "Creating new user with registration hash: #{registration_hash.to_yaml}"
unless registration_hash or resigration_hash.empty?
return nil
end
user = User.new
user.email = registration_hash[:email]
if registration_hash[:password]
user.password = registration_hash[:password]
else
user.password = Devise.friendly_token[0,20]
end
user.password_confirmation = user.password
# custom app code here...
if registration_hash[:skip_confirmation] == true
user.confirm!
end
user
end
Nota: Il mio login supporto app con altro servizio così ho implementato una tabella che contiene token di autenticazione.
Spero che questo possa farti iniziare.
L'opzione 'dialogo' sembra essere deprecato. Penso che "popup" sia l'equivalente in questi giorni. – drewww
Ora, anche Popup è ammortizzato @drewww –