In devise.rb
config.omniauth :facebook, app_id, 'app_secret', :scope => 'email', info_fields: 'email, name, address, birthday, age_range, first_name, gender, hometown, location '
In user.rb (model)
def facebook
#facebook ||= Koala::Facebook::API.new(self.oauth_token)
end
The oauth token for the user object is set and then the following is called.
user.facebook.get_object("me")
This is the response
{"name"=>"name", "id"=>"uid"}
I do not get any additional information like address, email, image link etc, although, if the user is made to sign in via omniauth-facebook, I get all the params. What should I do?
It's because each user has certain things restricted or granted by default, their security settings. Oauth, bumps the user and says "if you want access to this app, you'll need to agree to let us have these permissions on your account" -- the user says ok and you get the info you need. Users with certain security settings will also let you see other about-me info.
So... the simple answer is to use an oauth login. that will ensure the token you get back gives you access to the things you list in the scope.
Out of curiosity, is there a reason you aren't asking for oauth login already?
Related
I’m using Rails 4.2.7 with Omniauth 1.3.1. When someone logs into my app using Facebook, I’d like to record their birthday, however, I can’t figure out how to extract it from Facebook’s site when I got my auth object. I have this in my config/initializers/omniauth.rb file …
Rails.application.config.middleware.use OmniAuth::Builder do
…
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'],
scope: 'public_profile', info_fields: 'id,email,link,birthday,first_name,last_name'
but once my callback is returned to my application ..
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
The call dies because there is no birthday to extract …
def self.from_omniauth(auth)
puts "extra: #{auth.extra}"
bday = Date.strptime(auth.extra.raw_info.birthday,'%m/%d/%Y')
What is printed out in “extra:” is
extra: #<OmniAuth::AuthHash raw_info=#<OmniAuth::AuthHash first_name=“MyName” id="1777736954079999” last_name=“LastName” link="https://www.facebook.com/app_scoped_user_id/1777736954079999/">>
even though I definitely have a birthday set up in my Facebook profile. What else do I need to do to pass/extract the birthday information?
According with Facebook's Login documentation, the permission for public_profile doesn't include birthday information, but only the following fields: id, name, first_name, last_name, age_range, link, gender, locale, picture, timezone, updated_time, verified.
The user_birthday permission will give you access to date and month of a person's birthday. They also state that it may or may not include the year.
Try adding user_birthday to your scope.
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'],
scope: 'public_profile,user_birthday', info_fields: 'id,email,link,birthday,first_name,last_name'
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.
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"}
I have an app that uses omniauth to facebook auth. I also have a user access token. I'm using koala to access facebook graph api. However, I'm not sure how to pass koala my user access token to actually get access to the facebook pages that my user manages.
How do I get the pages that my user manages and pass the access token to do that?
api = Koala::Facebook::API.new(access_token)
pages = api.get_connections(user_id, "accounts")
this returns the collection of pages for which your user has access, inside of each page there's an "access_token" property, that token is the one that you need to use to manage that specific page
Since you are using omniauth for Facebook Authentication, you can add scope: manage_pages while defining provider in omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: 'publish_actions, email, manage_pages']
end
This will ask the user about the permissions required for managing pages.
Now, when you have the permision, Use Koala to get a list of pages user has using a Graph API call
koala = Koala::Facebook::API.new(#access_token)
# retrieve collection fo all your managed pages: returns collection of hashes with page id, name, category, access token and permissions
pages = #user_graph.get_connections('me', 'accounts')
Use the access_token property from the result of the previous call.
# get access token for first page
first_page_token = pages.first['access_token']
# or: retrieve access_token for a given page_id
page_token = #user_graph.get_page_access_token(page_id)
Use the page token to authenticate as a page and use Graph API as normal
#page_graph = Koala::Facebook::API.new(page_token)
#page_graph.get_object('me') # I'm a page
#page_graph.get_connection('me', 'feed') # the page's wall
#page_graph.put_wall_post('post on page wall') # post as page, requires new publish_pages permission
#page_graph.put_connections(page_id, 'feed', :message => message, :picture => picture_url, :link => link_url)
I have a rails app with two separate types of users (call them A and B). Right now they can both sign in with facebook. However, I need B to be able to oauth with some extended permissions, and I DO NOT want A to give me the extended permissions.
Inside config/initializers/devise.rb
config.omniauth :facebook, "API_KEY", "API_SECRET", :client_options => {:ssl => {:ca_path => ' /path/to/my/ssl/stuff'}}
I know I can add
:scope => "extended_permissions"
But I only want the extended permissions to happen when B users sign up.
Since this is in an initializer is this even possible? Or can I somehow config.omniauth elsewhere in the app and keep devise happy?
It's clearly explained in the documentation
If you want to set the display format, auth_type, or scope on a
per-request basis, you can just pass it to the OmniAuth request phase
URL, for example: /auth/facebook?display=popup or
/auth/facebook?scope=email.
source: https://github.com/mkdynamic/omniauth-facebook#per-request-options