我写了登录Facebook的代码,一切正常,我收到了用户的电子邮件地址。但Facebook上有另一个选项,允许用户选择我的应用程序可以访问的数据。
如果用户点击它,他会看到名称和标记为必需的所有内容,但电子邮件是可选的,用户可以将其从将要提供给应用的数据中删除。
在申请表上,需要发送电子邮件。那么我如何根据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("/");
});
答案 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
}));