passport-facebook icon indicating copy to clipboard operation
passport-facebook copied to clipboard

email is not returned

Open ashnamuh opened this issue 8 years ago • 16 comments

Hi,

I'm using nodejs and expressjs with passport-facebook for user to signup account with fb account. I found a facebook user account is not returning the email. The user don't signed up with the Phone number instead. Only email is saved in the account contact. In addition, the email has been verified. I don't know what is problem. Anyone has an idea?

My strategy

passport.use(new FacebookStrategy({
  clientID: facebookConfig.clientID,
  clientSecret: facebookConfig.clientSecret,
  callbackURL: facebookConfig.callbackURL,
  profileFields: ['id', 'displayName', 'name', 'gender', 'profileUrl', 'emails', 'photos'] // also 'email' is not working
  },
  function facebookHandler(accessToken, refreshToken, profile, cb) {
    if (!profile.emails || !profile.emails[0].value || !profile._json.email) {
      throw new UnprocessableEntity('No Email in Facebook');
    }
    let email = profile.emails[0].value || profile._json.email;

    User.findOne({
      where: {externalId: profile.id}
    })
    ...
  }
));

ashnamuh avatar Dec 26 '16 05:12 ashnamuh

+1 here. Same issue. Tried using 'email' and 'emails'. Nothing gets returned.

brnrc avatar Jan 10 '17 21:01 brnrc

You need to do the following when authenticating: passport.authenticate('facebook', {scope: 'email'}) Then, in your FacebookStrategy, request profileFields: [...'email'...]

rsnider19 avatar Jan 20 '17 13:01 rsnider19

Hi, I am having the same issue. Please see my code below. Not being able to request additional permissions... Any suggestions?

router.get('/auth/facebook', passport.authenticate('facebook', { scope: ['email']}));

passport.use(new FacebookStrategy({ clientID: ///// clientSecret: //// callbackURL: "http://localhost:8000/auth/facebook/callback", profileFields: ['id', 'email', 'displayName', 'photos'] },

orielbachar avatar Jan 25 '17 16:01 orielbachar

+1, requesting both in scope

passport.authenticate("facebook", {
   failureRedirect: "/login",
   scope: ["email"] ...

and profileFields:

profileFields: ['id', 'email', 'name'] ...

vvzen avatar Feb 14 '17 16:02 vvzen

After checking the official facebook APIs, it seems that passport is broken.. or there's something I don't get.

Here's a working url created by hand using the facebook docs (paste it in the browser adding your app id and you'll see the popup):

https://www.facebook.com/v2.8/dialog/oauth?client_id=your_app_id&redirect_uri=http://localhost:3000/auth/facebook/callback&scope=public_profile,email

screen shot 2017-02-15 at 20 14 11

And here's the url that passportjs generates (passing scope: ["public_profile", "email"] ) :

https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Ffacebook%2Fcallback&client_id=your_app_id

screen shot 2017-02-15 at 20 14 43

Clearly the scope doesn't get appended to the url, now we should investigate why and what's the right way to add scope to the request. .. maybe looking at the passport.authenticate() function in the source code could help?

@rsnider19 do you know something more?

vvzen avatar Feb 15 '17 19:02 vvzen

I used the following and it worked:

passport.use(new FacebookStrategy({
  clientId: ...,
  clientSecret: ...,
  callbackURL: ....,
  profileFields: ['id', 'displayName', 'email', 'first_name', 'middle_name', 'last_name']
}))

EyMaddis avatar Mar 17 '17 10:03 EyMaddis

I tried the following, and it is still not working.

  1. add email to scope passport.authenticate('facebook', { scope : ['email', 'public_profile'], session : false }),

  2. add email to profileFields profileFields: ["id", "birthday", "email", "first_name", "last_name", "gender", "picture.width(200).height(200)"],

When I tried the Graph API V 2.7 with me?fields=id,name,email, email is also not returned.

fei115 avatar Mar 21 '17 17:03 fei115

Try it

passport.use('facebook', new FacebookStrategy({
  clientID        : secret.facebook.clientID,
  clientSecret    : secret.facebook.clientSecret,
  callbackURL     : secret.facebook.callback,
  profileFields   : secret.facebook.profileFields
},

igorkokotko avatar Mar 24 '17 09:03 igorkokotko

For me this happens when users have restricted the visibility of their email address to only themselves.

jorrit avatar May 20 '17 08:05 jorrit

@rsnider19 , Thanks man your solution worked.

prdk0 avatar Oct 06 '18 11:10 prdk0

@rsnider19 Thanks man... Your solution works..... Guys go for it.....

amitfegade121 avatar Jun 11 '19 06:06 amitfegade121

The provided solutions (email in bot scope and in profileFields) work, and produce an object that looks just like the GoogleStrategy's. Any problems with the scope term missing from the URL (vyzen's post) appear resolved; it looked normal to me even when I was using the wrong scope strings. Recommend close.

MBerka avatar Mar 18 '20 08:03 MBerka

You can use specified strings in this URL https://developers.facebook.com/docs/facebook-login/permissions#reference-default

Below is a snippet for strategy configuration

const { Strategy } = require('passport-facebook');
const FacebookStrategy = Strategy;

exports.facebookStrategy = new FacebookStrategy(
  {
    clientID: process.env.FACEBOOK_CLIENT_ID,
    clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
    callbackURL: process.env.FACEBOOK_CALLBACK_URL,
    profileFields: [
      'email',
      'name',
      'displayName',
      'picture' ,
      'name_format',
      'short_name',
    ]
  },
  function(accessToken, refreshToken, profile, done) {
    done(null, profile);
  }
)

poode avatar Mar 22 '20 18:03 poode

I'm facing the same and I guess when it happens is something related to the following documentation and not passport it self:

email | string | The User's primary email address listed on their profile. This field will not be returned if no valid email address is available. Facebook Graph API User

I've just implemented this as an alternative:

      const { email, first_name, last_name, id} = profile._json;
      const userData = {
        email: email || id, // If there's no e-mail, uses user's Facebook id
        nome: `${first_name} ${last_name}`,
      };

I don't like it. But I hope it works.

robertoosantos avatar Mar 31 '21 15:03 robertoosantos

I used the following and it worked:

passport.use(new FacebookStrategy({
  clientId: ...,
  clientSecret: ...,
  callbackURL: ....,
  profileFields: ['id', 'displayName', 'email', 'first_name', 'middle_name', 'last_name']
}))

Works for me

shubhamdixit863 avatar Nov 11 '21 05:11 shubhamdixit863

May be you didn't added email in permision section of your meta developer console app.

Inside Meta developer console > go to your App > go to "Use Cases" > go to "Authentication and account creation customization "> in customiztion check the below "permisssion" section if email is added or not? meta

abid211051 avatar Feb 21 '24 06:02 abid211051