护照facebook登录后

时间:2018-02-16 13:46:06

标签: express react-native passport.js express-session passport-facebook

我正在创建一个React Native应用程序,用户应该可以使用Facebook登录(当然)。我在节点后端使用快速会话(与MongoDB结合存储会话)与护照(本地策略)和passport-facebook(Facebook策略)集成,以实现某种会话管理,用户不会在在关闭应用程序后,需要再次登录。 一切都适合当地的战略;用户可以登录,并在会话到期之前向API发出请求。 我试图让Facebook的策略正常运行,但我现在面临的问题是我几天来一直试图解决这个问题...

使用React Native,该应用程序将弹出一个窗口,询问您的Facebook凭据,询问该应用是否可以使用您的个人资料的必要信息。这发生在以下代码中:

// Set up Linking
componentDidMount() {
    // Add event listener to handle OAuthLogin:// URLs
    Linking.addEventListener('url', this.handleOpenURL);
    // Launched from an external URL
    Linking.getInitialURL().then((url) => {
        if (url) {
            this.handleOpenURL({ url });
        }
    });
}

componentWillUnmount() {
    // Remove event listener
    Linking.removeEventListener('url', this.handleOpenURL);
}

loginWithFacebook() {
    this.openURL('http://localhost:3002/v1/auth/facebook');
}

// Open URL in a browser
openURL(url) {
    // Use SafariView on iOS
    if (Platform.OS === 'ios') {
        SafariView.show({
            url: url,
            fromBottom: true
        });
    }
    // Or Linking.openURL on Android
    else {
        Linking.openURL(url);
    }
}

handleOpenURL({ url }) {
    const [, user_string] = url.match(/user=([^#]+)/);
    console.log(JSON.parse(decodeURI(user_string)));

    let result = JSON.parse(decodeURI(user_string));

    if(result.success) {
        this.props.loginFbComplete(result.user);
    } else {

    }

    if (Platform.OS === 'ios') {
        SafariView.dismiss();
    }
}
单击“登录”屏幕中的按钮时,将调用loginWithFacebook()。一切都按计划运行,因此Facebook开发者帐户已正确配置。 在后端,我的passport-facebook策略配置如下:

// Register Facebook Passport strategy
passport.use(new FacebookStrategy.Strategy(facebook,
    function (req, accessToken, refreshToken, profile, done) {
        process.nextTick(function() {
            Users.findOne(
                {
                    Provider: 'facebook',
                    ProviderId: profile.id,
                    Email: profile.emails[0].value
                }, (err, user) => {
                    if (err) {
                        return done(err, null);
                    } else {
                        if (!user) {
                            let providerData = profile._json;
                            providerData.accessToken = accessToken;
                            providerData.refreshToken = refreshToken;

                            let providerUserProfile = {
                                FullName: profile.displayName,
                                FirstName: profile.name.givenName,
                                LastName: profile.name.familyName,
                                Email: profile.emails[0].value,
                                Provider: 'facebook',
                                ProviderId: profile.id,
                                ProviderData: providerData,
                            };

                            let newUser = new Users(providerUserProfile);
                            newUser.save((err) => {
                                if (err) {
                                    return done(err, null);
                                } else {
                                    return done(null, newUser);
                                }
                            });
                        } else {
                            return done(null, user);
                        }
                    }
                }
            );
        });
    }
));

deserializeUser function:

passport.deserializeUser(function(id, done) {
   Users.findById(id, function(err, user) {
      done(err, user);
   });
});

serializeUser函数:

passport.serializeUser(function(user, done) {
    done(null, user._id);
});

对于身份验证路由,添加以下内容:

router.route('/auth/facebook')
.get((req, res, next) => {
    passport.authenticate('facebook')(req, res, next)
});

对于Facebook登录成功/失败后的回叫路线,添加以下内容:

router.route('/auth/facebook/callback')
.get(loginFbUser);
const loginFbUser = (req, res) => {
passport.authenticate('facebook', (error, user, info) => {
    let result = {};

    console.log('REQ SESSION 1', req.session);

    if (error || !user) {
        result = {success: false, message: info.message};
        return res.redirect('OAuthLogin://login?user=' + JSON.stringify(result))
    } else if (user) {
        req.login(user, loginErr => {
            if (loginErr) {
                result = {success: false, message: loginErr.message};
            } else {
                Users.findOneAndUpdate({_id: user._id}, {LastOnline: new Date()}, {new: true}).lean().exec((err, testUser) => {
                    if (err) {
                        result = {success: false, message: err.message};
                    } else if (!testUser) {
                        result = {success: false, message: 'User not found.'};
                    } else {
                        result = {success: true, user: testUser};
                    }

                    console.log('isAuthenticated?', req.isAuthenticated());
                    req.session.save(function() {
                        console.log('session after save', req.session);
                        res.redirect('OAuthLogin://login?user=' + JSON.stringify(result));
                    });
                });
            }
        });
    }
})(req, res);
};

第一个console.log显示会话中没有设置护照(user._id)的会话。 在req.login()函数之后,我可以清楚地看到用户通过req.isAuthenticated()方法进行了身份验证。我强迫用req.session.save()将会话保存到MongoDB。在最后一个console.log中,我可以看到与第一个console.log-statement的区别; user(_id)被添加到会话中。 我在我的React Native应用程序中重定向回正确的路由以捕获facebook登录的结果。问题出在这里:当我在登录后执行另一个请求时,用户会话消失了,它是空的,用户实际上未经授权执行对API的任何进一步请求,会话被清除,我有不明白为什么。

有没有人知道这可能是什么?

0 个答案:

没有答案