Save user's gender and location from youtube login OAuth - ruby-on-rails

I have youtube login setup with OAuth2 and upon a successful user registration I would like to save the users gender and location in the database.
Checking the OAuth docs https://developers.google.com/accounts/docs/OAuth2Login#userinfocall
you can see that you can access a users gender and location along with things like name, email and their profile picture.
Below is my code for saving a users info to the db
user.rb
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.picture = auth.info.image
user.gender = auth.info.gender
user.country = auth.info.locale
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
but using the auth.info.USER_INFO config doesn't seem to save these values to the database. Am i missing something?
Here are the parameters my app is asking for without any scopes.
UPDATE
I got this to work by passing in an extra scope for the userinfo.profile parameter. Remember to include full urls with no commas separated by a space.
Rails.application.config.middleware.use OmniAuth::Builder do
provider :youtube, YOUTUBE_KEY, YOUTUBE_SECRET, { :scope => "https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com", access_type: 'offline', approval_prompt: '' }
end
This got the following permissions

Can you post the code where you ask for OAuth scopes? My guess is that you aren't asking for the profile scope. Check out this site:
https://developers.google.com/oauthplayground/
If you're just using the YouTube sample code, you're probably not asking for the profile scope:
https://www.googleapis.com/auth/userinfo.profile
You can tell if you are asking for this scope or not when you hit the auth page, because the auth page will say something like:
"Google OAuth 2.0 Playground is requesting permission to:
View basic information about your account
View your name, public profile URL, and photo
View your gender and birthdate
View your country, language, and timezone"
I've attached a screenshot. If you're not seeing this, look to where you are configuring your scopes and add this to the list of OAUth scopes to authorize.

Related

How can I translate Facebook user data into records on my database?

I'm using the omniauth-facebook gem with devise to set up Facebook login on my website. I'm at the point of importing Facebook user data into my database, but I'm having some weird issues.
Here's my method used to import the data:
#User.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email.to_s
user.password = Devise.friendly_token[0,20]
user.username = auth.info.name
end
end
The record I get back has a user.username equal to the Facebook email, and the user.email is nil. auth.info.name (which is actually the email address) is the only piece of Facebook user data I'm actually able to recover. Everything else comes back nil.
Has anyone else encountered this?
Why are you using user instead of member inside of the first_or_create block? Is it a typo while creating a code snippet?
Anyway, I believe that the issue is for users that exists in database. In such case block that is passed to the first_or_create method isn't evaluated (yield is only for new records) so fields are not updated.
Make sure that you specified those fields (or didn't specified only name) in omniauth-facebook configuration: https://github.com/mkdynamic/omniauth-facebook. It returns name and email by default.
You should also take a look at the great RailsCasts about Facebook Authentication.

get first_name and last_name fields from facebook omniauth

I am now implementing omniauth feature into my app. Everything works fine except that i cant get the first and last name from the facebook. Here is my model code.
def self.from_omniauth(auth)
user = User.where(email: auth.info.email).first
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.email = auth.info.email
user.image = auth.info.image
user.password = Devise.friendly_token[0,20]
end
end
I already have the strong parameters setup properly for devise as am using that now for default authentication and is working properly.Is there any additional permissions necessary for first and last name from facebook?
After some fiddling around i found the solution. Now i think we have to explicitly require the fields we require. For me the fix is just to add first_name and last_name to facebook.
In my initializers i added first_name and last_name to info fields.
info_fields: 'email, first_name, last_name'
Update
My full config file will look like this now
config.omniauth :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_SECRET"], scope: 'email', info_fields: 'email, first_name, last_name'
From checking the Facebook docs, the first_name and last_name fields are both part of the public profile so your permissions should be fine.
No idea if this would work (in fact, I would kind of hope it doesn't), but in the implementation we've got working in production at the moment we're using Hash accessors instead of methods. So:
new(
first_name: oauth_data["info"]["first_name"],
last_name: oauth_data["info"]["last_name"],
...
Given your email etc fields are getting set correctly, I'd be surprised if trying that works, but it might be worth a shot.
Failing that, have you got any validations or before_create callbacks which could be interfering somehow?
Ran into this issue while designing the OAuth flow for an app that was using Devise + omniauth-facebook.
Using the public_profile scope, you get back a name attribute on the auth hash.
request.env["omniauth.auth"]
My issue is that a user has one profile and it is autosaved ( user is required to enter a first name and last name at sign up which is validated on the profile model)
Solution: Create a name parsing method in your omniauth services model, which you can pass the request.env["omniauth.auth"]["info"]["name"] as an argument.
# auth hash returns a name like "John Doe Smith"
def parse_name_from_string(ful_name_string)
name_array = name_string.split(" ") # break apart the name
# I chose to return a PORO so i can do something like parsed_user_name_from_facebook_auth.first_name
{
last_name: name_array.pop,
first_name: name_array.join(" ")
}
end

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.

How to get Facebook user's email using the Koala gem

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"}

How to Fix Blank Email Error when User Signs up with Facebook (through Omniauth)

I allow Facebook authentication on my Rails website and use Omniauth for it. I recently received the following error in production:
ActiveRecord::RecordInvalid: Validation failed: Email can't be blank,
Email is invalid
Normally Facebook signup works fine, so what would cause this specific error? Below is my code for creating a User with Omniauth.
def self.create_from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth[:info][:email]
user.password = SecureRandom.urlsafe_base64(n=10)
user.save!
end
end
Actually, there has been a lot of discussion about this issue in the omniauth-facebook repo.
I think the user TeamRainless is the one who got closest to the answer:
Some users have supplied a phone number which facebook uses as it's main authentication method instead of the email address. I believe the phone number is then encrypted and that becomes what the email address would normally be.
The only solution to this problem is to redirect the user to a form where the registration process will be completed. Check out the Railscasts OmniAuth Part 2 episode on how to do this.

Resources