passport-facebook - cant get about_me and email profile fields

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:

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

Answers


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'}));

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


Need Your Help

Join Date and Time to DateTime in C#

c# datetime

I am retrieving data from an iSeries where there is a separate date and time fields. I want to join them into a DateTime field in my C# project. I don't see a way to add just a time to a DateTime f...

Using Bash to display a progress indicator

bash shell unix progress

Using a bash only script, how can you provide a bash progress indicator?