Facebook 登录在用户个人资料中返回“未定义”字段,并且不返回电子邮件。 MEANJs + Passport-facebook

Posted

技术标签:

【中文标题】Facebook 登录在用户个人资料中返回“未定义”字段,并且不返回电子邮件。 MEANJs + Passport-facebook【英文标题】:Facebook Login is returning 'Undefined' Fields in user profile and it doesn't return email. MEANJs + Passport-facebook 【发布时间】:2015-10-29 20:51:57 【问题描述】:

我正在使用 Meanjs.org 样板,Facebook 注册将我返回到注册页面。 以下是我到目前为止所采取的步骤。

1) 设置 Facebook 应用站点 URL

http://localhost:3000/

以及回调OAuth的URI

http://localhost:3000/auth/facebook/callback

2) 将 APP_ID 和 APP_Secret 作为 Client_ID 和 Client_Secret 放入

    facebook: 
    clientID: process.env.FACEBOOK_ID || '*****',
    clientSecret: process.env.FACEBOOK_SECRET || '*****',
    callbackURL: 'http://localhost:3000/auth/facebook/callback',
    profileFields: ['id','emails', 'first_name', 'last_name', 'displayName', 'link', 'about_me', 'photos' ]
,

3) 代码如下

--路线

// Setting the facebook oauth routes
app.route('/auth/facebook').get(passport.authenticate('facebook', 
    scope: ['email']
));
app.route('/auth/facebook/callback').get(users.oauthCallback('facebook'));

-- oauthCallback 函数,

    exports.oauthCallback = function(strategy) 
    return function(req, res, next) 
        passport.authenticate(strategy, function(err, user, redirectURL) 
            if (err || !user) 
                console.log('1' + err);
                //console.log(user);
                return res.redirect('/#!/signin');
            
            req.login(user, function(err) 
                if (err) 
                    console.log('2' + err);
                    return res.redirect('/#!/signin');
                

                return res.redirect(redirectURL || '/');
            );
        )(req, res, next);
    ;
;

-- Passport-Facebook 策略

module.exports = function() 
// Use facebook strategy
passport.use(new FacebookStrategy(
        clientID: config.facebook.clientID,
        clientSecret: config.facebook.clientSecret,
        callbackURL: config.facebook.callbackURL,
        passReqToCallback: true
    ,
    function(req, accessToken, refreshToken, profile, done) 

        console.log('facebook Strategy Started');
        // Set the provider data and include tokens
        var providerData = profile._json;
        providerData.accessToken = accessToken;
        providerData.refreshToken = refreshToken;

    //  console.log(JSON.stringify(profile));
        console.log(profile);

    //  console.log(JSON.stringify(profile.name.givenName));

        // Create the user OAuth profile
        var providerUserProfile = 
            firstName: profile.name.givenName,
            lastName: profile.name.familyName,
            displayName: profile.displayName,
            email: profile.emails[0].value,
            username: profile.username,
            provider: 'facebook',
            providerIdentifierField: 'id',
            providerData: providerData
        ;

        //console.log('provider' + providerUserProfile);
        // Save the user OAuth profile
        users.saveOAuthUserProfile(req, providerUserProfile, done);
    
));

;

4) 调试

在oauthCallback函数下记录err返回如下,

1TypeError: 无法读取未定义的属性“0”

Facebook 在 Passport-Facebook 模块中作为个人资料返回的内容如下,

id: 'Id_of_the_person', 用户名:未定义, displayName: 'Full_name_of_person', 姓名: familyName:未定义, 给定名称:未定义, 中间名:未定义 , 性别:未定义, profileUrl:未定义, 提供者:“脸书”, _raw: '"name":"Full_name_of_person","id":"Id_of_the_person"', _json: 名称:'Id_of_the_person', id: 'Id_of_the_person', accessToken: 'access_token_value', refreshToken: 未定义

谁能指导我从 Facebook 获取正确的用户个人资料,包括用户电子邮件?

非常感谢。

【问题讨论】:

API v2.4关于字段的变化,见developers.facebook.com/docs/apps/changelog#v2_4_changes //实际发出的API请求需要相应修改;如果您的框架/SDK 没有向您公开该请求,那么您需要让他们调整他们的代码。 在样板文件中检查 passport-facebook 的版本。我也遇到过类似的情况,升级到 2.0.0 版解决了这个问题。 【参考方案1】:

我的个人资料字段设置为以下

profileFields: ['email','id', 'first_name', 'gender', 'last_name', 'picture']

即使您设置了电子邮件,如果用户有多个电子邮件,它也可能会返回电子邮件。因此,您需要检查是否返回了电子邮件 profile.email 或 profile.emails[0].value。您还必须检查它是否未定义,因为有些人在 Facebook 注册时从不验证他们的电子邮件帐户,有些人使用电话号码注册,在这两种情况下,他们的电子邮件将始终未定义。

您想检查所有必填字段是否有值。

var email = profile.email || profile.emails[0].value;
            if (! email)
              console.log('this user has no email in his FB');
              var err = message:'this user is missing an email';
              return done(err);
            

如果他们有电子邮件,我现在可以这样做

newUser.facebook.email = email;

如果他们没有电子邮件,您可以为个人资料设置会话并将他们发送到要求他们输入电子邮件的页面。

这听起来很痛苦,但你永远不能相信来自第三方 api 的信息具有价值。

我在网上看到的大多数护照示例都是错误的。他们都假设存在电子邮件。

【讨论】:

【参考方案2】:

首先,profileFields 字段不符合 Portable Contacts convention - 您可以找到 passportjs here 的约定。

其次,在您的示例中,删除已删除的“about_me”后,Facebook 注册不会返回错误。在删除“about_me”之前,我遇到了另一个错误:尝试访问节点类型(用户)上不存在的字段(about_me)

如果错误仍然存​​在,请参阅this 系列 5 教程,这有助于我在注册页面上使用社交网络帐户进行身份验证。

【讨论】:

以上是关于Facebook 登录在用户个人资料中返回“未定义”字段,并且不返回电子邮件。 MEANJs + Passport-facebook的主要内容,如果未能解决你的问题,请参考以下文章

迁移到 Swift 3 时,Facebook 登录不会返回应用程序

如果用户在登录后更改了他的 Facebook 个人资料详细信息,如何在我的应用程序中更新 Facebook 个人资料?

用户登录时解析获取 facebook 个人资料图片

使用 Facebook 登录我的应用

使用 URL 显示 Facebook 用户图片 (Swift 5 | Xcode 10)

Facebook API:如何在facebook中获取登录用户的关注者列表[重复]