passport.js,在popup窗口中进行身份validation后,closures它并redirect父窗口

在我的node.js express应用程序中,我使用passport.js集成了Facebook身份validation。 我可以在popup窗口中打开Facebooklogin页面,然后login。 在这个阶段,redirect发生在popup窗口中。 但我需要closurespopup窗口,并在父窗口中进行redirect( 即父窗口将redirect )。 我要在这里粘贴完整的代码, 虽然我认为主要问题是在模板文件(.ejs)中。

在SO里,我找不到类似的问题。

// Passport session setup. passport.serializeUser(function(user, done) { done(null, user); }); passport.deserializeUser(function(obj, done) { done(null, obj); }); // Use the FacebookStrategy within Passport. passport.use(new FacebookStrategy({ clientID: config.facebook_api_key, clientSecret:config.facebook_api_secret , callbackURL: config.callback_url }, function(accessToken, refreshToken, profile, done) { console.log(" id = "+profile.id); process.nextTick(function () { //Check whether the User exists or not using profile.id //Further DB code. profile.user_id="00000444000555"; return done(null, profile); }); } )); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); //app.set('view engine', 'jade'); app.use(cookieParser()); app.use(bodyParser.urlencoded({ extended: false })); app.use(session({ secret: 'keyboard cat', key: 'sid'})); app.use(passport.initialize()); app.use(passport.session()); app.use(express.static(__dirname + '/public')); //Router code app.get('/', function(req, res){ res.render('index', { user: req.user }); }); app.get('/account', ensureAuthenticated, function(req, res){ console.log(req.user); res.render('account', { user: req.user }); }); //Passport Router app.get('/auth/facebook', passport.authenticate('facebook')); app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect : '/', failureRedirect: '/login' }), function(req, res) { res.redirect('/'); }); app.get('/logout', function(req, res){ req.logout(); res.redirect('/'); }); function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect('/login') } app.listen(8000); 

而模板文件是:

 <script type="text/javascript"> if (window.location.hash && window.location.hash == '#_=_') { if (window.history && history.pushState) { window.history.pushState("", document.title, window.location.pathname); } else { // Prevent scrolling by storing the page's current scroll offset var scroll = { top: document.body.scrollTop, left: document.body.scrollLeft }; window.location.hash = ''; // Restore the scroll offset, should be flicker free document.body.scrollTop = scroll.top; document.body.scrollLeft = scroll.left; } } </script> <% if (!user) { %> <div style="width:500px;height:180px;"> <h2 style="font-size:40px;">Welcome! Please log in.</h2> <a href="javascript:void(0)" onclick=" window.open('/auth/facebook','',' scrollbars=yes,menubar=no,width=500, resizable=yes,toolbar=no,location=no,status=no')"><img src="fb-login.jpg" width="151" height="24"></a> </div> <% } else { %> <script type="text/javascript"> window.parent.location.href ="/"; window.close(); </script> <h2>Hello, <%= user.displayName %>.</h2> <% } %> 

我上面的评论也许没有完整的答案,所以这是我在我的网站上做的完整解决scheme。

在我的节点后端,我创build了一个基本上路由到一个特殊的页面,称为after-auth.html成功validation后,如此

 app.get('/auth/twitter/callback', auth.passport.authenticate('twitter', { failureRedirect: '/failedLogin.html' }), function(req, res) { res.redirect('/after-auth.html'); }); 

我的后auth.html页面只是简单地把焦点放在父页面上,并像这样closures自己

 <script type="text/javascript"> if (window.opener) { window.opener.focus(); if(window.opener.loginCallBack) { window.opener.loginCallBack(); } } window.close(); </script> 

您可能还会注意到我调用了一个名为loginCallBack的函数。 我使用这个作为一个钩子,所以父浏览器知道成功validation后更新其模型/视图。 例如,在我的loginCallBack中,我检查用户是否login并删除所有“login”button,并用用户的configuration文件图像replace它们。例如

  var loginCallBack = function() { loginCntr.checkLogin(); } 

我们自己一直在努力,最终编写了一个简单的JavaScript插件来帮助我们使用这个https://github.com/enhancv/popup-tools

使用它会在客户端上这样:

 <button id="button">Facebook Login</button> <script> document.getElementById("button").onclick = function () { popupTools.popup('/popup-url', "Facebook Connect", {}, function (err, user) { if (err) { alert(err.message); } else { // save the returned user in localStorage/cookie } }) </script> 

在服务器上:

 passport.use(new FacebookStrategy({ clientID: process.env.FACEBOOK_ID, clientSecret: process.env.FACEBOOK_SECRET, callbackURL: '/calback-url', }, function (accessToken, refreshToken, profile, done) { // process facebook profile into user })); app.post('/popup-url', passport.authenticate('facebook')) app.get('/callback-url', passport.authenticate('facebook'), function (req, res) { res.end(popupTools.popupResponse(req.user)) } ); 

希望人们会发现这有用。