passport-facebook in nodejs - profile fields

omerkarj picture omerkarj · Dec 8, 2013 · Viewed 7.6k times · Source

some of the profile fields i am trying to get from Facebook when logging in a user, are not going through.

I am using passportjs in node. this is the facebook strategy:

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

being used with:

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

the result is that 'link', 'about_me' and 'email' are not getting pulled while the other fields are.

Answer

aturkelson picture aturkelson · Mar 3, 2014

The profileFields parameter adheres to the Portable Contacts convention. This means you would want to use 'emails' instead of 'email'. As for the "about_me" field, it does not appear as if passport-facebook supports the OpenSocial protocol fully. This means you're out of luck if you want to use the "profileFields" parameter for both of these profile elements. The following code snippet, taken from the master branch, illustrates this limitation:

Strategy.prototype._convertProfileFields = function(profileFields) {
    var map = {
    'id':          'id',
    'username':    'username',
    'displayName': 'name',
    'name':       ['last_name', 'first_name', 'middle_name'],
    'gender':      'gender',
    'profileUrl':  'link',
    'emails':      'email',
    'photos':      'picture'
};
...

The fields listed in this mapping are the only ones supported right now.

Fortunately all is not lost. If you choose not to use the profileFields parameter then oddly enough you will be sent the "about_me" content you are interested in via a property called "bio". Here's how you could access that:

passport.use(new FacebookStrategy({
  clientID: FACEBOOK_APP_ID,
  clientSecret: FACEBOOK_APP_SECRET,
  callbackURL: FACEBOOK_CALLBACK_URL
},
function(accessToken, refreshToken, profile, done) {
   console.log("bio: " + profile._json.bio);
}));

Unfortunately this doesn't give you the other data you were interested in. I'm guessing that in your situation you are probably looking at gathering the supported convention fields during the passport-facebook callback and then grabbing the extended profile fields in a followup call using the facebook api directly. Either that or poke the passport-facebook maintainers to extend their field support.