email field is optional in passportjs facebook strategy

佐手、 提交于 2019-12-08 00:04:11

问题


I wrote the code for login with facebook, everything works and I'm getting the user's email address. But there is another option on facebook which lets the user select the data my application is going to have access to.

If user clicks on that, he'll see the name and everything marked as required, but email is optional and the user can remove it from the data that is going to be provided to the app.

On the application, email is required. So how I can mark the email as required on facebook?

This is the snippet I'm using in the code.

passport.use(new FacebookStrategy({
        clientID: config.social.facebook.clientID,
        clientSecret: config.social.facebook.clientSecret,
        callbackURL: config.url+'auth/facebook/cb',
        enableProof: false,
        profileFields:['id', 'name', 'emails'],
        scope: "email"
    }, function(accessToken, refreshToken, profile, done) {
        // doing the rest of the thing
    }
));

// ...

app.get('/auth/facebook', passport.authenticate('facebook', {scope: ['email']}));
app.get('/auth/facebook/cb', passport.authenticate('facebook'), function(req, res, next) {
    res.redirect("/");
});

回答1:


I solved the problem by re-requesting the permission.

Turns out I can add authType: 'rerequest' to passport.authenticate('facebook', {scope: ['email'], authType: 'rerequest'}).

What I did is to check if the emails field is present in the result, if not, I call done with an error.

function(accessToken, refreshToken, profile, done) {
    if (profile.emails === undefined) {
        done('email-required')
        return;
    }
    // doing the rest of the thing
}

Then to catch the error, I had to write a custom callback for passport.authenticate('facebook').

app.get('/auth/facebook/cb', function(req, res, next) {
    passport.authenticate('facebook', function (err, user, info) {
        if (err) {
            if (err == 'email-required') res.redirect('/auth/facebook/rerequest');
            // check for other kinds of errors and show proper messages
            return;
        }
        req.user = user;
        // do the rest of the thing
    })(req, res, next)
});

As you see, I redirect the user to another route /auth/facebook/rerequest in case of error.

app.get('/auth/facebook/rerequest',
    passport.authenticate('facebook', {
        scope: ['email'],
        authType: 'rerequest' // this is important
    }
));

This will redirect the user to the same page on FB again and this time email field is required. I couldn't do this in the same route; apparently it was using the same generated code to communicate to fb which was not acceptable by fb.

And that's how I managed to solve the issue.




回答2:


you need to specify email in Strategy in profileFields property

passport.use('facebook', new FacebookStrategy({
  clientID: config.facebook.appId,
  clientSecret: config.facebook.appSecret,
  callbackURL: config.facebook.callbackURL,
  profileFields: ['emails', 'first_name', 'last_name', 'locale', 'timezone']
}, function (token, refreshToken, profile, done) {
  // you will get emails in profile.emails
}));


来源:https://stackoverflow.com/questions/34164571/email-field-is-optional-in-passportjs-facebook-strategy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!