17

I am able to retrieve basic user information via passport-facebook, following the below code and saving in mongodb:

app.get("/auth/facebook", passport.authenticate("facebook", { scope : ["email", "publish_stream", "user_location", "user_hometown", "user_birthday", "read_friendlists"]}));

app.get("/auth/facebook/callback", passport.authenticate("facebook",{ successRedirect: '/', failureRedirect: '/'}));

var mongoose = require('mongoose'), 
FacebookStrategy = require('passport-facebook').Strategy, 
Users = mongoose.model('Users');

module.exports = function (passport, config) { 
passport.serializeUser(function(user, done) { 
    done(null, user.id);
}); 

passport.deserializeUser(function(id, done) { 
    Users.findOne({ _id: id }, function (err, user) { 
        done(err, user); 
    });
});

passport.use(new FacebookStrategy({ 
    clientID: config.facebook.clientID,
    clientSecret: config.facebook.clientSecret,
    callbackURL: config.facebook.callbackURL 
}, function(accessToken, refreshToken, profile, done) { 
    Users.findOrCreateFaceBookUser(profile, done);
}));};

However, I am not able to see the profile picture in the "profile".

The documentation https://github.com/jaredhanson/passport-facebook says to retrieve photos we need to pass the profileFields as below. But doing so, I am able to see the photo URL but loosing other data which were contained in _json e.g. profile._json.location.name. How can I retrieve photo with other user information intact?

passport.use(new FacebookStrategy({
// clientID, clientSecret and callbackURL
profileFields: ['id', 'displayName', 'photos', ....]},// verify callback));
laggingreflex
  • 32,948
  • 35
  • 141
  • 196
user2897777
  • 273
  • 1
  • 4
  • 10
  • Did you ever figure this one out? – chrisco512 Apr 20 '14 at 10:39
  • 1
    Yes, the picture can be accessed via the graph api using the access token like this. "https://graph.facebook.com/" + profile.username + "/picture" + "?width=200&height=200" + "&access_token=" + accessToken; There is no need to use the profile fields. – user2897777 Apr 21 '14 at 18:14

5 Answers5

27

If you need a larger image (default in miksii's example above is 50px x 50px which is pretty small), then use:

profileFields: ['id', 'displayName', 'name', 'gender', 'picture.type(large)']

and then

picture: profile.photos ? profile.photos[0].value : '/img/faces/unknown-user-pic.jpg'

This will return a 200px x 200px profile picture for that user.

Tebbers
  • 484
  • 7
  • 12
16

In addition to answer of your question - you don't have to do it that way. As you mentioned you can define the required attributes for Facebook profile:

  clientID: "...",
  clientSecret: "...",
  callbackURL: "...",
  profileFields: ['id', 'displayName', 'name', 'gender', ..., 'photos']

What than you can do is just simply grab the value of the given attribute. Let's say you want to make an attribute that will hold this value:

picture: profile.photos ? profile.photos[0].value : '/img/faces/unknown-user-pic.jpg'

This proved to be a better solution since some users or sometimes the value of username may be undefined.

I hope you find this useful too,

Thank you.

miksiii
  • 2,426
  • 26
  • 22
  • I know this is over a year old, but can you explain why you use the structure with ? and : instead of just setting a value? Trying to understand what is going on, thank you :) – leofontes Aug 25 '16 at 19:08
  • It is shorten if - else conditional structure where ? means "in case profile.photos returns true" and : means "in case profile.photos returns false". Regarding to that, if there is no photos we want to set the default picture for our user (this picture rest in the specified path img/faces/unknown..jpg). – miksiii Aug 27 '16 at 13:37
  • ooooooh okay, got it! Thank you :D – leofontes Aug 30 '16 at 19:01
9

Yes, the picture can be accessed via the graph api using the access token like this. "graph.facebook.com/"; + profile.username + "/picture" + "?width=200&height=200" + "&access_token=" + accessToken; There is no need to use the profile fields.

user2897777
  • 273
  • 1
  • 4
  • 10
1

As this answer, it will be work better with this code.

passport.use(new FacebookStrategy({
  clientID: FACEBOOK_APP_ID,
  clientSecret: FACEBOOK_APP_SECRET,
  callbackURL: FACEBOOK_APP_CALLBACK,
  profileFields: ['id', 'displayName', 'picture.type(large)', 'email', 'birthday', 'friends', 'first_name', 'last_name', 'middle_name', 'gender', 'link']
}, (accessToken, refreshToken, profile, cb) => {
  const picture = `https://graph.facebook.com/${profile.id}/picture?width=200&height=200&access_token=${accessToken}`
  //
}))
nakorndev
  • 803
  • 2
  • 11
  • 18
0

2020 solution

Get users accessToken from passportjs passport-facebook strategy.
Use this token to get json with a url for an users avatar:

https://graph.facebook.com/me/picture?access_token=${accessToken}&&redirect=false