I have a rails app where users can log through facebook with oauth.
I retrieve their image, email and name. What I'd like to do is scrap their profile link (http://facebook.com/name) and gender (male,female, other)
But It doesn't work for link and gender, here is my integration:
Gemfile
gem 'omniauth-facebook'
User.rb model
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
user.gender = auth.info.gender # assuming the user model has a gender
user.link = auth.info.link # assuming the user modal has a link
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
EDIT
devise.rb
config.omniauth :facebook, "***", "***"
But for all users, gender and link return 'nil'
Any ideas what I could be missing ?
Thanks
The url parameter doesn't work now, the correct name of the field is link
config.omniauth :facebook, 'APP_ID', 'APP_SECRET', {scope: 'email', info_fields: 'email,name,verified,gender,link'}
There is a list of attributes we can get from Facebook:
https://developers.facebook.com/docs/facebook-login/permissions/v2.5#reference-public_profile
https://developers.facebook.com/docs/graph-api/reference/user
You need to specify the scope and fields you want to get when you specify the provider in config/initializers/devise.rb
I.e.:
config.omniauth :facebook, 'APP_ID', 'APP_SECRET', {scope: 'email', info_fields: 'email,name,verified,gender,url'}
Whether or not facebook will give you all the data you ask for is a different question.
Related
I have Rails 5 app using Facebook Omniauth on Devise and I want to pull the user's public_profile info such as first_name, last_name, age_range, link, gender, locale, verified, user_location, and user_status into my Users table. Right now, it only gets email when using the default Devise setup:-
# user.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.username = auth.info.name
user.photo = auth.info.image
user.skip_confirmation!
user.save
# devise.rb
config.omniauth :facebook, '..', '..', image_size: 'large'
I tried to edit those files to get the details, but it doesn't work:-
# devise.rb
config.omniauth :facebook, '..', '..', image_size: 'large', scope: 'email, public_profile, user_location, user_status', info_fields: 'first_name, last_name, gender, age_range, etc.'
# user.rb
user.first_name = auth.extra.raw_info.first_name
user.last_name = auth.extra.raw_info.last_name
user.age_range = auth.extra.raw_info.age_range
user.gender = auth.extra.raw_info.gender
user.address = auth.info.user_location
user.status = auth.info.user_status
I don't know how to write the above properly to get them to work. I have permission to get user_location and user_status
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!
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
It is present in auth.
auth.info.email
Very simple question.
I have run into the "Email can't be blank" issue with my rails app/omniauth/facebook login. There are many questions on this, and among the answers is that some users give their telephone number and not their email addresses. However in my case, I have a facebook account open, with an email address that works fine with omniauth in development, but when I use it production it comes back email can't be blank. My credentials are correct.
Can anyone explain how you could have this combination of events?
edit: here is my controller code (keep in mind my devise model is "Member" and there is an associated profile model "User"
def provider
auth = request.env["omniauth.auth"]
member_email_check = Member.find_by_email(auth.info.email)
if member_email_check.present? && User.find_by_member_id(member_email_check.id)
sign_in_and_redirect member_email_check
return false
else
member = Member.where(provider: auth.provider, uid: auth.uid).first_or_create do |member|
member.provider = auth.provider
member.uid = auth.uid
member.email = auth.info.email
end
end
if auth.provider == "facebook"
if member.save
unless User.find_by_member_id(member.id)
User.create(:member_id => member.id,
:full_name => auth.info.first_name + " " + auth.info.last_name,
:first_name => auth.info.first_name,
:last_name => auth.info.last_name,
:email => auth.info.email,
:picture => auth.info.image)
end
sign_in_and_redirect member
else
session["devise.member_attributes"] = member.attributes
redirect_to new_member_registration_url
end
end
end
alias_method :facebook, :provider
end
SOLVED!
config.omniauth :facebook, "<YOUR API KEY>", "<YOUR SECRET KEY>", scope: 'email', info_fields: 'email,name,first_name,last_name,gender'
just added the email scope and info_fields.
I'm using the omniauth-linkedin gem to allow users to log into my Rails application using their LinkedIn account. I'm currently using auth.info.image to store the user's LinkedIn profile image URL:
user.rb
def self.from_omniauth(auth)
where(auth.slice(:provider, :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.linkedin_photo_url = auth.info.image
user.password = Devise.friendly_token[0,20]
end
However, the image is very small (50x50). Is there another method besides auth.info.image I could use in order to pull the large profile image found on the user's main profile page?
Thanks!
EDIT: I'm using the omniauth-linkedin and omniauth gems. It looks like the linkedin gem has a method with an option to determine image size but I'm struggling with implementing it with the omniauth-linkedin gem. This readme explains that it's possible but the explanation is lacking some details. Can someone help me figure this out?
https://github.com/skorks/omniauth-linkedin#using-it-with-the-linkedin-gem
I know it's been awhile, but I was just looking for this and thought I'd leave it here. The solution is fine, but will cause an extra call. Omniauth is already doing a fetch of the profile so we just have to tell it to also get the original picture
linkedin_options = {
scope: 'r_fullprofile r_emailaddress',
fields: ['id', 'email-address', 'first-name', 'last-name', 'headline', 'location', 'industry', 'picture-url', 'public-profile-url', "picture-urls::(original)"]
}
provider :linkedin, app_id,app_secret, linkedin_options
pictureUrls will be available in the extra info.
To get the image, use auth_hash[:extra][:raw_info][:pictureUrls][:values].first
One way to retrieve profile image in original size is by making separate API call.
include gem 'linkedin'
create initializer file /config/initializers/linkedin.rb with content:
LinkedIn.configure do |config|
config.token = "your LinkedIn app consumer_key"
config.secret = "your consumer_secret"
end
in your self.from_omniauth method replace line
user.linkedin_photo_url = auth.info.image
with
client = LinkedIn::Client.new
client.authorize_from_access(auth.extra.access_token.token, auth.extra.access_token.secret)
user.linkedin_photo_url = client.picture_urls.all.first
DONE
image = auth.extra.raw_info.pictureUrls.values.last.first
This is using a combination of the omniauth gem, devise, and paperclip that works for me:
config/initializers/devise.rb
config.omniauth :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'],
scope: 'r_basicprofile r_emailaddress',
fields: ['id', 'email-address', 'first-name', 'last-name', 'picture-urls::(original)']
app/models/user.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create.tap do |user| # .tap will run the |user| block regardless if is first or create
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.firstname = auth.info.first_name
user.lastname = auth.info.last_name
if auth.provider == 'facebook'
user.avatar = URI.parse(auth.info.image)
elsif auth.provider == 'linkedin'
user.avatar = URI.parse(auth.extra.raw_info.pictureUrls.values.last.first)
end
user.skip_confirmation!
end
end
I want to get a user's position information from their LinkedIn profile (company name, title, etc), but I can't get anything more than basic profile information (id, name, email, headline, and image). I'm guessins this is just a syntax thing since I'm requesting access to all fields upon user's authentication.
from 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.headline = auth.info.headline
**user.company = auth.info.company**
user.avatar = auth.info.image
user.password = SecureRandom.urlsafe_base64(n=6)
user.save!
end
from devise.rb
config.omniauth :linkedin, "abcdefghijk", "abcdefghijk",
# :scope => 'r_basicprofile r_emailaddress rw_nus r_fullprofile r_contactinfo r_network rw_company_admin',
# :fields =>
:scope => 'r_basicprofile r_emailaddress rw_nus r_fullprofile r_contactinfo r_network rw_company_admin',
:fields => ["id", "email-address", "first-name", "last-name",
"headline", "industry", "picture-url", "public-profile-url",
"location", "connections", "skills", "date-of-birth", "phone-numbers",
"educations", "three-current-positions" ]
Do I need to add fields to devise.rb or am I being an idiot and formatting user.company = auth.info.company wrong?
Thanks!
[edit]
okay, found it. The devise.rb field definition is wrong. (Probably outdated, I used the same and it was copied from somewhere.)
Correct name now is just "positions", not "three-current-positions"
After that, auth.extra.info.positions becomes available (with these params: https://developer.linkedin.com/docs/fields/positions)
The format for accessing user info id is:
user.name = auth["info"]["name"]