How to get Facebook user's email using the Koala gem - ruby-on-rails

I'm trying to use FB Open Graph to let my app update a user's attribute. I have Koala installed and using facebook-omniauth for my authentication. Simply I would like query my database looking for a user that matches his fb id and if that user does not exist then I would like to update the user model's attributes with data from the facebook API. Also I'm using mongoid as oppose to active record for my database.
In my user model I have this method.
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
end
Within my controller I have these lines of code within one of my methods.
#user = User.where(facebook_uid: params[:auth_id])
if #user.empty?
User.create(
first_name: User.facebook.get_object("name"),
last_name: User.facebook.get_object("email"),
facebook_uid: params[:auth_id],
facebook_oauth_token: params[:auth_token])
else
User.update_attributes(
facebook_oauth_token: params[:auth_token]
end
User.facebook.get_object("email") does not return me a user's email when I play around in my console. Does anybody have any idea how to do so?
Thanks!

This should work:
graph = Koala::Facebook::API.new(oauth_access_token)
profile = graph.get_object('me', fields:'email')
Now profile['email'] will get you the email of the user.

Try this:
facebook = Koala::Facebook::API.new(oauth_token)
public_attributes = facebook.get_object("me")
if public_attributes does not return email, this means that the user has not authorized the email for your App. check that you add "email" scope to the OAuth authorization process. If you use devise, this is the config:
config.omniauth :facebook, "facebook_app_key", "facebook_app_secret", {scope: "email"}

Related

Omniauth-Facebook giving error in callback - Email can't be blank?

Hi my devise login appears to work, but for some reason Facebook is not sending me the email in my API request. Then I am getting this error:
I read up on the July 18th, 2015 adjustment and added scope. No luck. Here is the initializer:
config.omniauth :facebook, ENV['FACEBOOK_APP_KEY'],
ENV['FACEBOOK_APP_SECRET'], scope: 'email', info_fields:'email,name'
Maybe I'm missing something on the FB Developer Page?
You will have to handle it :
Some Facebook users have unverified emails, so Facebook will not give it to you
There is Facebook users with only telephone numbers and no email
Facebook allow the user to not provide some information to your app, for example the email
It happens with profiles with unverified emails and when user choose not to provide your app with their email
rescue that error and redirect user to normal sign up page so they continue with providing their email address
Ok, if what Nicolas is saying is correct then you can easily solve this problem. Before save populate some fake and unique email with "+":
Add to your User model something like this:
class User < ActiveRecord::Base
before_validation :adjust_email, on: :create
private
def adjust_email
self.email = "fake+#{generate_token}" if email.blank?
true
end
def generate_token
rand(36**8).to_s(36)
end
end
And you will have to show your user this fake email, so that she will be able to login with it later. A downside of this solution is that you will not be able to send emails to such users, but maybe you don't want to.
What Remon suggested is also a valid option to redirect to sign up in case you get this particular error.
So, it all depends on what you actually plan to do with the email.

Rails koala getting omniauth user's groups

I want to get a visitor groups. It works just fine when I am connected with my account (the administrator of the app) but when I connect with another account the groups.count == 0
def index
if (#current_visitor)
#graph = Koala::Facebook::API.new(#current_visitor.oauth_token)
groups = #graph.get_connections("me", "groups").select
puts groups.count
end
end
end
You need to ask user for groups permission.
In case you're using omniauth-facebook, just add :scope => 'user_groups' to your configuration, besides app id and app secret.
Detail of permission with facebook login can be found here https://developers.facebook.com/docs/facebook-login/permissions/v2.2

Devise + Omniauth-Facebook get user's phone #

I'm using Devise for authentication in my Rails 3.2 app and am having trouble configuring omniauth-facebook to get the new user's phone number.
First of all: I'm not even sure that it's possible to get a phone number, so if that's the case and someone knows for sure, I'd be happy just for a confirmation.
It doesn't appear from https://github.com/mkdynamic/omniauth-facebook that "phone" is part of the FB auth hash by default, though the general Omniauth schema does have .info.phone (not required, of course). So my first idea was that it's a FB permissions problem. I'm not sure what permissions to use, though, as the Permissions with Facebook Login page doesn't say where to find the phone value (maybe this means it's just not possible?).
I have phone as a required attribute on the User model, so when I try to get it through FB the new object never persists. It works fine without looking for a phone number.
My config file:
# /config/initializers/devise.rb
config.omniauth :facebook, 'FACEBOOK_APP_ID', 'FACEBOOK_APP_SECRET', scope: 'email,public_profile', display: 'page'
In my user model:
# user.rb
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.phone = auth.extra.raw_info.phone # have also tried auth.info.phone
end
end
Thanks in advance for any help you may be able to provide!
There's currently no way to get a user's phone number from Facebook.
Facebook's Graph API reference lists all the user information that you can access via the API. A user's phone number is not on the list.
Also, to inspect the contents of the auth hash, add the following line of code at the beginning of your authentications/sessions/callbacks controller action:
render :text => "<pre>" + env["omniauth.auth"].to_yaml and return
You'll see that there is no phone field at auth.extra.raw_info or auth.info.

Devise, OmniAuth & Facebook - How to let user edit password?

I'm hoping that someone else has a good solution for this issue. We let our users register using facebook (by liking an app), and at the same time they enter our database as users on our site.
Upon successful registration it seems like Devise/OmniAuth is creating a random password(?). How can I let users edit their profile, which (and should) by default in Devise requires that they enter their current password?
I had the exact same issue so I hope my solution will be helpful.
Based off the details in your question I am assuming you following the OmniAuth guide in the devise wiki: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
In the following method:
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end
I changed the logic in the else block because it was creating a new user in the database right away and hashing a password for them:
else # Create new user
user =User.new
user
end
Instead I just made a new user so that after getting the facebook info I direct them to the sign up page where I have their info populated in the form fields where they can edit and create a password.
You will just need to make sure to update your
def self.new_with_session(params, session)
to add all the relevant facebook information you grabbed for a new user and assign it to the new user object so all those fields are populated with their information in the sign up page. So that after they finish typing their password and adding or changing any info and click submit it create the new user. Hopefully you find this helpful.
This was a mash of ideas for the wiki page on Devise and the railscast omniauth tutorial: http://railscasts.com/episodes/235-omniauth-part-1
Had a similar problem, but in regards to updating a user profile without password confirmation. Posting a link to it - hope it helps:
stackoverflow - Allowing users to edit accounts without saving passwords in devise

How do I fetch the access token for a user using the Twitter gem and the Omniauth gem when the users is already logged in?

Currently I authenticate the user using omniauth. This looks like this in my sessions controller and works well:
def create
auth = request.env['omniauth.auth']
unless #auth = Authentication.find_from_hash(auth)
# Create a new user or add an auth to existing user, depending on
# whether there is already a user signed in.
#auth = Authentication.create_from_hash(auth, current_user)
end
# Log the authorizing user in.
self.current_user = #auth.user
redirect_to authentications_url, :notice => "You've signed in!"
end
After this, I've stored the twitter uid in my authentications table (I also use linkedin, facebook) and I think that the twitter sessions has been closed.
How do I now authenticate so that I can use the Twitter gem? I think it should be something like this if I was calling it right after the omniauth callback.
token = auth['credentials']['token'],
secret = auth['credentials']['secret']
Twitter.oauth_token = token
Twitter.oauth_token_secret = secret
I clearly need to restart the session and put the token and secret in the right place. How can I create a method to do this?
You need to store both the token and the secret provided by Twitter in your authentications table (Authentication.create_from_hash). As long as you're doing that, this should work:
twitter_credentials = current_user.authorizations.find_by_provider(:twitter)
Twitter.oauth_token = twitter_credentials.token
Twitter.oauth_token_secret = twitter_credentials.token_secret
That's assuming that in your authentications table you store the Twitter token and secret as token and token_secret, as well as storing the provider as twitter

Resources