护照-Facebook身份验证未为所有Facebook账户提供电子邮件

57

我正在使用Passport-Facebook进行认证。

  passport.use(new FacebookStrategy({
            clientID: 'CLIENT_ID',
            clientSecret: 'CLIENT_SECRET',
            callbackURL: "http://www.example.com/auth/facebook/callback"
        },
        function (accessToken, refreshToken, profile, done) {            
            process.nextTick(function () {                
               console.log(profile)
            });               
        }
    ));

对于一些Facebook账号,我无法获取email_id信息。我尝试使用以下scope变量:

profileUrl : " " and ProfileFields : ['','']

但仍然无法获取email_id。

并不是每个Facebook帐户都设置了电子邮件地址... (人们也可以使用他们的手机号码注册FB。) - CBroe
但是我没有从那些有电子邮件的帐户收到电子邮件,而要注册 Facebook 我们需要有电子邮件地址,对吧? - AMT
我没有看到你在任何地方请求“电子邮件”权限... 你说你尝试使用了范围,但是在哪里?而且不,人们不必提供电子邮件地址才能注册FB,就像我之前说的那样。 - CBroe
请确保在那里记录accessToken并使用Graph API Explorer进行尝试。确保左侧的“电子邮件”权限未变灰。如果是,您没有在正确的时间请求范围。请参见passport-facebook项目上的此评论 - a paid nerd
https://dev59.com/PWEi5IYBdhLWcg3wBH6J 这解决了我的问题。试试这个。 - NOOBIEBOY97
7个回答

136

确保您的代码包含以下两个要素:

  passport.use(new FacebookStrategy({
            clientID: 'CLIENT_ID',
            clientSecret: 'CLIENT_SECRET',
            callbackURL: "http://www.example.com/auth/facebook/callback"
            passReqToCallback : true,
            profileFields: ['id', 'emails', 'name'] //This
        },

还有这个:

app.get('/connect/facebook', passport.authorize('facebook', { scope : ['email'] }));

这将使您可以访问以下内容:

  • profile.id
  • profile.name.givenName
  • profile.name.familyName
  • profile.emails

最后一项是一个数组,因此使用profile.emails [0] .value来获取用户的第一个电子邮件地址。

正如shamim reza指出的那样,您可能需要检查profile.emails!== undefined,因为该属性仅存在于用户至少有一个经过验证的电子邮件地址的情况下。

正如Weft指出的那样,您可能需要使用属性email而不是emails


1
meanjs的样板缺少profileFields这一行。 - zambono
1
哇,你救了我的一天。大家都在谈论作用域,但没有人谈论profileFields。 - llamerr
1
请给他“最佳答案” :) - Tzook Bar Noy
3
确实需要使用"profileFields"字段。此外,我不需要"passReqToCallback"。我在passport-facebook中搜索了一下,但没有找到它(我猜它没有被使用,所以你可以忽略它)。 - marcelocra
2
如果登录用户的电子邮件未经验证,则Facebook不会发送电子邮件字段。 - reza.cse08
显示剩余2条评论

26

1
设置您的策略时,请确保包括“profileFields”字段。仅在此处添加“scope”是不够的(至少对我来说是这样)。有关更多信息,请查看其他答案:https://dev59.com/CGAh5IYBdhLWcg3wDfoW#32370813。 - marcelocra
我接收到了一些用户的电子邮件,但是有些用户却没有收到?有什么原因吗? - Sandip Subedi
1
@SandipSubedi 看起来问题已经被下面的vinesh回答了。 - sifxtreme

8

我想在这里添加更多的信息。

当创建FacebookStrategy时添加profileFields:['emails'],并使用passport.authorize('facebook',{scope:['email']})可以解决大多数用户的问题。

然而,如果用户身份验证后仍无法获取其电子邮件,则可能存在其他原因。

  • 帐户上没有电子邮件地址
  • 帐户上没有确认的电子邮件地址
  • 帐户上没有经过验证的电子邮件地址
  • 用户必须重新确认其电子邮件地址才能通过安全检查点,但他们尚未这样做
  • 用户的电子邮件地址无法访问

确保您的用户不会遇到上述任何问题,详细信息请参见: https://developers.facebook.com/bugs/1802930019968631/


3
当护照没有返回profile.emails,profile.name.givenName,profile.name.familyName字段或者它们缺失时,您可以尝试解析https://graph.facebook.com/v3.2/ url,但您仍然需要一个token。您可以使用有效的token访问url,例如:

https://graph.facebook.com/v3.2/me?fields=id,name,email,first_name,last_name&access_token=

它会输出一个JSON响应,如下:
{
   "id": "5623154876271033",
   "name": "Kurt Van den Branden",
   "email": "kurt.vdb\u0040example.com",
   "first_name": "Kurt",
   "last_name": "Van den Branden"
}

安装 request 模块 ($ npm install request --save),用于解析 JSON url,并在您的 passport.js 文件中:

const request = require("request");

passport.use(new FacebookStrategy({
        clientID        : 'CLIENT_ID',
        clientSecret    : 'CLIENT_SECRET',
        callbackURL     : "https://example.com/auth/facebook/callback"
    },
    function(req, token, profile, done) {

        let url = "https://graph.facebook.com/v3.2/me?" +
                  "fields=id,name,email,first_name,last_name&access_token=" + token;

        request({
            url: url,
            json: true
        }, function (err, response, body) {
              let email = body.email;  // body.email contains your email
              console.log(body); 
        });
    }
));

你可以在url中添加很多其他参数,但其中一些需要用户允许才能返回值。你可以在以下网址进行尝试:https://developers.facebook.com/tools/explorer/


3

请确保将作用域参数提供给第一个 .authenticate() 调用,而不是回调函数。

像这样:

router.get("/auth/facebook", passport.authenticate("facebook", {
    scope: [ "email" ], // scope goes here, not below
}));

router.get("/auth/facebook/callback",
    passport.authenticate("facebook", {
        successRedirect: "/",
        failureRedirect: "/login",
    }),
);

-1

-3
passport.use(new FacebookStrategy({
        clientID: 'CLIENT_ID',
        clientSecret: 'CLIENT_SECRET',
        callbackURL: "http://www.example.com/auth/facebook/callback"
    },
    function (accessToken, refreshToken, profile, done) {            
        process.nextTick(function () {                
           console.log(profile)
        });               
    }
));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接