Passport.js, after authentication in a popup window, close it and redirect the parent window

In my node.js express application, I have enabled Facebook authentication using passport.js . I can open the Facebook login page in a pop-up window, after which the login occurs. At this point, redirection occurs in a popup window. But I need to close the popup and do the redirection in the parent window (i.e. the Parent window will be redirected). I am going to paste the full code here , although I think the main problem is in the template file (.ejs).

And I could not find any solution to similar issues there in 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); 

And the template file:

 <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 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> <% } %> 
+6
source share
2 answers

My comment above may have been an incomplete complete answer, so here is my complete solution that I make on my site.

In my node backend, I created a route that is mainly routed to a special after-auth.html page with successful authentication, for example,

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

My after-auth.html page just has javascript that returns focus to the parent page and closes this way

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

You may also notice that I am calling the loginCallBack function. I use this as a hook, so the parent browser knows how to update its model / views after successful authentication. For example, in my loginCallBack I check if the user is logged in and deleted all the login buttons and replaced them with a user profile picture for example.

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

We struggled with this ourselves and ended up writing a simple javascript plugin to help us with this https://github.com/enhancv/popup-tools

Using this on the client will be like this:

 <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> 

On server:

 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)) } ); 

Hope people find this helpful.

+1
source

Source: https://habr.com/ru/post/982163/


All Articles