在passportjs facebook strategy

时间:2015-12-08 19:40:15

标签: node.js passport.js facebook-login facebook-oauth passport-facebook

我写了登录Facebook的代码,一切正常,我收到了用户的电子邮件地址。但Facebook上有另一个选项,允许用户选择我的应用程序可以访问的数据。

enter image description here

如果用户点击它,他会看到名称和标记为必需的所有内容,但电子邮件是可选的,用户可以将其从将要提供给应用的数据中删除。

enter image description here

在申请表上,需要发送电子邮件。那么我如何根据Facebook上的要求标记电子邮件?

这是我在代码中使用的代码段。

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("/");
});

2 个答案:

答案 0 :(得分:4)

我通过重新请求许可来解决问题。

原来我可以将authType: 'rerequest'添加到passport.authenticate('facebook', {scope: ['email'], authType: 'rerequest'})

我所做的是检查结果中是否存在emails字段,如果没有,我会调用done并显示错误。

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

然后要抓住错误,我必须为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)
});

如您所见,如果出现错误,我会将用户重定向到另一条路线/auth/facebook/rerequest

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

这将再次将用户重定向到FB上的同一页面,这次需要电子邮件字段。我无法在同一条路线上做到这一点;显然它使用相同的生成代码与fb进行通信,这是fb无法接受的。

这就是我设法解决问题的方法。

答案 1 :(得分:0)

您需要在profileFields属性

中的策略中指定电子邮件
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
}));