电子邮件字段在passportjs facebook策略中是可选的

我写了Facebook的login代码,一切正常,我得到用户的电子邮件地址。 但在Facebook上有另一个选项,让用户select我的应用程序将有权访问的数据。

在这里输入图像说明

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

在这里输入图像说明

在应用程序上,电子邮件是必需的。 那么如何在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("/"); }); 

我通过重新请求权限解决了这个问题。

原来,我可以将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 } 

然后为了赶上错误,我不得不写一个自定义callbackpassport.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) }); 

如您所见,如果有错误,我将用户redirect到另一个路由/auth/facebook/rerequest

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

这将再次将用户redirect到FB上的同一页面,此时需要电子邮件字段。 我不能在同一条路线上这样做; 显然它使用相同的生成代码来沟通fb这是不被fb接受的。

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

您需要在profileFields属性中的Strategy中指定电子邮件

 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 }));