电子邮件字段在 passportjs facebook 策略中是可选的
email field is optional in passportjs facebook strategy
我编写了使用 facebook 登录的代码,一切正常,我正在获取用户的电子邮件地址。但是 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
}
然后为了捕获错误,我不得不为 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 不能接受的。
这就是我设法解决问题的方法。
您需要在 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
}));
我编写了使用 facebook 登录的代码,一切正常,我正在获取用户的电子邮件地址。但是 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
}
然后为了捕获错误,我不得不为 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 不能接受的。
这就是我设法解决问题的方法。
您需要在 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
}));