2015-02-08 4 views
6

Nella mia app express node.js, ho integrato l'autenticazione di Facebook usando passport.js. Posso aprire la pagina di accesso di Facebook in una finestra popup, quindi l'accesso avviene. A questo punto, il reindirizzamento avviene nella finestra popup. Ma ho bisogno di chiudere la finestra popup e di effettuare il reindirizzamento nella finestra genitore (, ad esempio, la finestra padre reindirizzerà). Inserirò il codice completo qui anche se penso che il problema principale sia nel file modello (.ejs).passport.js, dopo l'autenticazione nella finestra pop-up, chiudilo e reindirizza la finestra genitore

E non sono riuscito a trovare alcuna soluzione nelle domande simili là fuori 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); 

E il file di modello è:

<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> 
<% } %> 
+0

Forse questo aiuta? http://www.webdeveasy.com/single-page-application-authentication/ Non è lo stesso stack, ma potresti essere in grado di prendere in prestito la loro idea – kane

+0

@kane praticamente, ma stanno usando angolare per inviare indietro msg a finestra genitore ... im ora mi chiedo come posso fare questo senza angolare ... sembra di aprire un socket e inviare un messaggio a me stesso può funzionare, ma sembra eccessivo # –

risposta

16

mio commento di cui sopra è stato forse a corto di una risposta completa, quindi ecco la mia soluzione completa che faccio sul mio sito.

Nel mio nodo back-end, ho creato un itinerario che, in fondo rotte per una pagina speciale chiamato dopo-auth.html su autenticazione riuscita in questo modo

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

mio post-auth.html pagina deve semplicemente javascript che mette concentrarsi di nuovo sulla pagina genitore e si chiude in questo modo

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

     if(window.opener.loginCallBack) { 
     window.opener.loginCallBack(); 
     } 
    } 
    window.close(); 
</script> 

Si può inoltre notare che invoco una funzione chiamata loginCallBack. Lo uso come un hook in modo che il browser principale sappia aggiornare il suo modello/viste dopo l'autenticazione avvenuta con successo. Ad esempio, nel mio loginCallBack, controllo se l'utente ha effettuato l'accesso e rimuove tutti i pulsanti di "accesso" e li sostituisce con l'immagine del profilo dell'utente ad es.

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

Sì, ho appena capito ieri dopo aver postato il mio commento, che posso accesso genitore dalla finestra modale, in questo momento sto implementando la stessa cosa, che hai descritto qui, ma come ho capito c'è un problema con IE a volte dicendo che windows.opener non è definito a causa di alcuni criteri di IE, ma IE supporta showModalDialog che è ammortizzato da Chrome può ancora essere un'alternativa a window.open() per IE. E grazie per la risposta) –

+0

Lasciami testare e vedere –

1

Abbiamo lottato con noi stessi e questo ha finito per scrivere un semplice plugin javascript per aiutarci con questo https://github.com/enhancv/popup-tools

Usandolo sarebbe andato come questo sul client:

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

Spero che le persone lo trovino utile.

+0

Super! Senza fastidi. Solo una domanda veloce Funziona con tutti i browser? – kittu

+0

Cosa succede se voglio mostrare opzioni come fb e google in popup e inviare una richiesta.L'ho provato ma la risposta ritorna come err – kittu