passport-facebook - cant get about_me and email profile fields
Asked Answered
P

2

18

I am trying to establish a login system for my app using passport-facebook. everything goes well except for the 2 fields that are getting undefined back from the request.

I will post my entire code for the login procedure, since I haven't seen a lot of info about it here even though there are a lot of question in the matter.

this is the configuration in app.js

var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;

passport.serializeUser(function(user, done) {
  done(null, user.facebookId);
});
passport.deserializeUser(function(id, done) {
  routes.findUserById(id, function(err, user) {
    done(err, user);
  });
});

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: FACEBOOK_CALLBACK_URL,
    profileFields: ['id', 'displayName', 'link', 'about_me', 'photos', 'email']
  },
  routes.handleLogin
));

using passport initialize and session

app.use(passport.initialize());
app.use(passport.session());

actual request handling, notice I am using the correct scope

app.get('/auth/facebook', passport.authenticate('facebook', { scope: ['user_about_me', 'email'] }));
app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/error' }));

and this is my user creation function in the router

exports.handleLogin = function(accessToken, refreshToken, profile, done) {
  db.userCatalog.findOne({ facebookId: profile.id }, function(err, existingUser) {
    if (err) {
      return done(err);
    }
    else {
      if(existingUser) {
        console.log('User: ' + existingUser.name + ' found and logged in!');
        done(null, existingUser);
        } 
      else {
        new db.userCatalog({
        name: profile.displayName,
        facebookId: profile.id,
        link: profile.link,
        picture: profile.photos[0].value,
        bio: profile.about_me,
        email: profile.email
        }).save(function (err, data) {
          if (err) {
            return done(err);
          }
          else {
            console.log('New user: ' + data + ' created and logged in!');
            done(null, data);
          }
        });
      }
    }
  });
};

and the result when creating a new user after finishing the login procedure: enter image description here

I am sure this is some rookie mistake, but I just can't figure it out myself...

Phyllous answered 29/11, 2013 at 18:8 Comment(2)
the profile field I am using are based on the Facebook FQL reference: developers.facebook.com/docs/reference/fqlPhyllous
see my answer https://mcmap.net/q/661705/-passport-facebook-authentication-is-not-providing-email-for-all-facebook-accountsLycia
B
39

Facebook returns some of the default attributes. If you want to access more details about client's profile you would have to declare it under the FacebookStrategy:

passport.use(new FacebookStrategy({

        clientID: "...",
        clientSecret: "...",
        callbackURL: "...",
        profileFields: ['id', '...', '...', 'photos', 'emails']

      }, ...

So once you declare the attributes you would like to receive from Facebook, when someone try to log into your system he will be asked to share his photos or emails with you/your app. Once he approve this you can access its values:

profile.photos[0].value,
profile.emails[0].value,
...

For emails, sometimes it is useful to change:

passport.authenticate('facebook');

To this:

passport.authenticate('facebook', { scope: 'email'}));
Builtup answered 25/1, 2015 at 21:40 Comment(2)
Perfect! Works great. I found adding the { scope: 'email' } was requiredInalienable
are there other "scopes" we should use to get other info ?Floss
B
8

In the profileFields you shoul use emails (plular) instead of email (singular):

profileFields: ['id', 'displayName', 'link', 'about_me', 'photos', 'emails']

This is noted in the facebook-passport documentation README.md:

profileFields parameter which specifies a list of fields (named by Portable Contacts convention)

And you can find Portable Contacts conventions for passportjs here

Beatify answered 17/2, 2014 at 18:41 Comment(1)
This is right, but I needed to also change 'about_me' to 'about' in order for the code to process and avoid an error.Verecund

© 2022 - 2024 — McMap. All rights reserved.