Passport-Facebook authentication is not providing email for all Facebook accounts
Asked Answered
G

7

57

I am using Passport-Facebook authentication.

  passport.use(new FacebookStrategy({
            clientID: 'CLIENT_ID',
            clientSecret: 'CLIENT_SECRET',
            callbackURL: "http://www.example.com/auth/facebook/callback"
        },
        function (accessToken, refreshToken, profile, done) {            
            process.nextTick(function () {                
               console.log(profile)
            });               
        }
    ));

For some of the Facebook accounts I don't get the email_id and I even tried by using a scope variable such as below, but still I am unable to get the email_id.

profileUrl : " " and ProfileFields : ['','']

Garrick answered 5/4, 2014 at 12:26 Comment(5)
Not every FB account has an email address set … (People are able to sign up for FB using their mobile number as well.)Marathon
but i am not getting email from accounts which have email and to get registered to fb we need to have email id right??Garrick
I don’t see you ask for email permission anywhere … you said you tried to use scope, but where? And no, people do not have to give an email address to register for FB, as I already said.Marathon
Make sure to log accessToken there and try it with the Graph API Explorer. Make sure that the "email" permission on the left is not greyed out. If it is, you're not asking for the scope at the right time. See this comment on the passport-facebook project.Elston
#21775698 This solves my issue. Try this.Priscilapriscilla
W
136

Make sure these two things are in your code:

  passport.use(new FacebookStrategy({
            clientID: 'CLIENT_ID',
            clientSecret: 'CLIENT_SECRET',
            callbackURL: "http://www.example.com/auth/facebook/callback"
            passReqToCallback : true,
            profileFields: ['id', 'emails', 'name'] //This
        },

and this:

app.get('/connect/facebook', passport.authorize('facebook', { scope : ['email'] }));

This gives you access to the following:

  • profile.id
  • profile.name.givenName
  • profile.name.familyName
  • profile.emails

The last one being an array, so use profile.emails[0].value to get the first email address of the user.

As shamim reza pointed out, you might want to check if profile.emails !== undefined because the property only exists if the user has at least one verified email address.

As Weft pointed out, you might have to use the property email instead of emails.

Wesleywesleyan answered 3/9, 2015 at 8:37 Comment(7)
The meanjs boiler plate is missing the profileFields lineLabel
whoa, you saved my day. everyone talking about scope but no one about profileFieldsModulator
give him "best answer" :)Antoninus
One really need the 'profileFields' field. Besides, I didn't need the passReqToCallback. I searched in passport-facebook for that and it is not there (I guess it is not used, so you might leave it out).Nitrogen
what if the user didnt verified his email on facebook?Poser
@ArslArsl if login user email is not verified, then facebook does not send email fieldsLionel
Fails for me if I use "emails" in the profileFields array. Works if I use "email" instead.Enchondroma
S
26

When you are authenticating use something similar to this. You need to use add 'email' in the scope when you authenticate.

app.get('/auth/facebook',
passport.authenticate('facebook', { scope: ['email']}),
    function(req, res){
});

That has worked for me.

Here were a few links that helped me out.

https://github.com/jaredhanson/passport-facebook/issues/11 https://github.com/jaredhanson/passport-facebook#how-do-i-ask-a-user-for-additional-permissions

Sorrow answered 18/7, 2014 at 0:54 Comment(3)
Make sure to include the 'profileFields' field when setting up your strategy. Only adding 'scope' in here won't do the trick (at least didn't for me). For more info, look the other answer: https://mcmap.net/q/661705/-passport-facebook-authentication-is-not-providing-email-for-all-facebook-accounts.Nitrogen
I am getting emails for some users but not for some users ? Any reasons for that ?Bolection
@SandipSubedi it seems like that question is answered by vinesh belowSorrow
F
8

I would like to add more information here.

While adding profileFields: ['emails'] while creating FacebookStrategy and passport.authorize('facebook', { scope : ['email'] }) solves issue for most of the users.

There are other possible reasons where you will not get user's email after authentication.

  • No e-mail address on account
  • No confirmed e-mail address on account
  • No verified e-mail address on account
  • User entered a security checkpoint which required them to reconfirm their e-mail address and they have not yet done so
  • User's e-mail address is unreachable

​ you need to make sure that your user does not have any of the issues listed above. more information can be found https://developers.facebook.com/bugs/1802930019968631/

Follansbee answered 1/4, 2017 at 19:11 Comment(0)
K
3

When passport doesn't return the profile.emails, profile.name.givenName, profile.name.familyName fields, or if they are missing, you can try to parse the https://graph.facebook.com/v3.2/ url, although you still need a token. You access the url, with of course a valid token, like:

https://graph.facebook.com/v3.2/me?fields=id,name,email,first_name,last_name&access_token=

It outputs a JSON response like:

{
   "id": "5623154876271033",
   "name": "Kurt Van den Branden",
   "email": "kurt.vdb\u0040example.com",
   "first_name": "Kurt",
   "last_name": "Van den Branden"
}

Install the request module ($ npm install request --save), to be able to parse a JSON url and in your passport.js file:

const request = require("request");

passport.use(new FacebookStrategy({
        clientID        : 'CLIENT_ID',
        clientSecret    : 'CLIENT_SECRET',
        callbackURL     : "https://example.com/auth/facebook/callback"
    },
    function(req, token, profile, done) {

        let url = "https://graph.facebook.com/v3.2/me?" +
                  "fields=id,name,email,first_name,last_name&access_token=" + token;

        request({
            url: url,
            json: true
        }, function (err, response, body) {
              let email = body.email;  // body.email contains your email
              console.log(body); 
        });
    }
));

You can add a lot of other parameters to the url, although some of them require user permission to return values. You can play with it on: https://developers.facebook.com/tools/explorer/

Kravits answered 28/10, 2018 at 15:30 Comment(0)
H
3

Make sure you're providing the scope parameter into the first .authenticate() call, not the callback.

Like this:

router.get("/auth/facebook", passport.authenticate("facebook", {
    scope: [ "email" ], // scope goes here, not below
}));

router.get("/auth/facebook/callback",
    passport.authenticate("facebook", {
        successRedirect: "/",
        failureRedirect: "/login",
    }),
);
Hubble answered 8/7, 2019 at 12:17 Comment(0)
N
-1

You can use the code provided as an example in the passport-facebook site as a starting point. Then, to get access to email, make sure to check @Forivin's answer.

Nitrogen answered 15/4, 2017 at 19:18 Comment(0)
P
-3
passport.use(new FacebookStrategy({
        clientID: 'CLIENT_ID',
        clientSecret: 'CLIENT_SECRET',
        callbackURL: "http://www.example.com/auth/facebook/callback"
    },
    function (accessToken, refreshToken, profile, done) {            
        process.nextTick(function () {                
           console.log(profile)
        });               
    }
));
Pistol answered 29/5, 2016 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.