Search code examples
node.jspassport.jspassport-facebook

Can't get email information from Facebook passport


currently I am working on a project to store information from Facebook Authentication, I already checked Passport-facebook doesn't get email to see the solution, and here is my code

passport.use(new FacebookStrategy(
  {
    clientID: 'xxxxxxxxxxxxx',
    clientSecret: 'xxxxxxxxxxxxxxxx',
    callbackURL: 'http://1bc600b4.ngrok.io/auth/facebook/callback',
    profileFields: ['id', 'displayName', 'name', 'photos', 'email'],
  },
  (accessToken, refreshToken, profile, done) => {
    console.log(profile);
    models.User.findOne({ where: { facebookID: profile.id } }).then((existinguser) => {
      if (existinguser) {
        // Nothing will happen, the ID already exists
        done(null, existinguser);
      } else {
        models.User.create({
          // email: profile.emails[0].value,
          username: 'hello',
          firstname: profile.name.givenName,
          lastname: profile.name.familyName,
          facebookID: profile.id,
          avatar: `https://graph.facebook.com/${profile.id}/picture?redirect=true&height=470&width=470`,
          avatarThumb: profile.photos[0].value,
          last_login: Date.now(), }).then(user => done(null, user));
      }
    });
  },
));

app.use(passport.initialize());

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

app.get(
  '/auth/facebook/callback',
  passport.authenticate('facebook', { session: false }),
  (req, res) => {
    res.send('AUTH WAS GOOD!');
  },
);

I don't understand why I use this way and the email information still not show up, which makes me lose a lot of information, can anyone give me a hint on solving this prob? Thank you!


Solution

  • This problem has been there for a while, you need to include email scope and even then it might not send facebook email because of user privacy settings or if the user's email is not verified at the facebook's end.

    You could add scope like this:

    passport.use(
       new FacebookStrategy({
                clientID: 'CLIENT_ID',
                clientSecret: 'CLIENT_SECRET',
                callbackURL: "http://www.example.com/auth/facebook/callback"
                passReqToCallback : true,
                profileFields: ['emails'] // email should be in the scope.
       })
    )
    

    Also you would need to add this to your authorize route as well,

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

    If the emails return, It will be an list of it and you could access them like this:

    1. profile.emails // [[email protected], [email protected]]
    2. profile.emails[1].value // [email protected]
    

    If it doesn't return, you can use their username or id and create a facebook email atleast temporarily like this:

    [email protected] // this exists.