Search code examples
ruby-on-railsfacebookomniauthomniauth-facebook

How to get the Facebook user email from omniauth for Rails 4?


How can i get Facebook user email by omniauth for Rails? This is my omniauth.rb

OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, ENV['FACEBOOK_KEY'] , ENV['FACEBOOK_SECRET'], :scope => 'email', :display => 'popup', :info_fields => 'name,email'
end

This is my model

def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
      puts "auth.providerauth.providerauth.providerauth.provider"
      puts auth.info.inspect

      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.username = auth.info.name.gsub(" ","") + new_token
      user.email = auth.info.email
      user.password = digest(new_token)
      user.save!
    end
  end

But i only got this from the info

auth.providerauth.providerauth.providerauth.provider
#<OmniAuth::AuthHash::InfoHash image="http://graph.facebook.com/xxxx" name="xxx xxxx">

Seems like no email in return. But i need the email to pass my model validation so what should i do?

Thanks!


Solution

  • in theory the user.auth.info.email should be the case

    https://github.com/mkdynamic/omniauth-facebook

    ... but in reality Facebook don't necessary need to return email if user don't want to publish email. (for example Twitter will never give you response with email)

    so the approach where you creating user directly from what Oauth callback returns may be wrong for you.

    if you really rally need an email from user, try rather saving whatever the OAuth returns to an Identity model and then if email is present create User and if email is not present prompt the user to provide the email in "finish signup form" that will create the user.

    Think about it: Technically speaking Oauth is a protocol where user can signup to your application without providing any credentials => the Provide-UID is what defines him not the email

    So you either split the way how you handle session to User(email&password) or Identity(OAuth) so someting like current_user || current_identity in your controllers ....or you will link them when email is provided