2012-06-12 10 views
6

Ich versuche, den Passport mit connect in meinen nodejs-Server zu integrieren, aber es scheint nicht richtig zu funktionieren. Alle Leitfäden/Beispiele verwenden expressJS, also habe ich mein Bestes versucht, den Code so umzuformatieren, dass er mit meinem Code funktioniert, aber ich kann es nicht funktionieren lassen. Die zugehörigen Teile sind unten beschrieben. Hat jemand einen Rat, was das Problem sein könnte? pass.authenticate() scheint nie aufgerufen zu werden (zumindest die console.log-Nachricht im Facebook-Authentifizierungs-Callback wird nie gedruckt). Ich speichere gerade nichts in einer Datenbank, daher sollte das Problem hoffentlich etwas sehr Einfaches sein, das ich gerade vermisse.Verwenden von PassportJS mit Connect für NodeJS zum Authentifizieren von Facebook-Benutzern

Das einzige, was mir in den Sinn kommt, ist der potentielle Rückruf, den ich für Facebook habe, das ist eine localhost-URL (da ich diese noch lokal entwickle). Ich war in der Lage, mich mit facebook zu authentifizieren, indem ich everauth verwendete (von einer rein lokalen Instanz), aber zu passJS wechselte, da ich dort verschiedene Probleme hatte, mit denen sich passJS zu befassen schien.

passport = require('passport'); 
    fpass = require('passport-facebook').Strategy; 

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

passport.use(new fpass({ 
     clientID:'facebook app id', 
     clientSecret:'facebook app secret', 
     callbackURL:'http://localhost:3000/auth/facebook/callback' 
    }, 
    function(accessToken, refreshToken, fbUserData, done){ 
     console.log('got here'); 
     return done(null,fbUserData); 
    } 
)); 



    function checkLoggedIn(req, res, next){ 
     console.log("req.user: " + req.user); 
     if(req.user) 
      next(); 
     else{ 
      console.log('\nNot LOGGED IN\n'); 
      if(req.socket.remoteAddress || req.socket.socket.remoteAddress == '127.0.0.1'){ 
       var folder,contentType; 
       console.log('req url = '+req.url); 
       if(req.url == '/'){ 
        folder = __dirname + '/landingPage.html'; 
        contentType = 'text/html'; 
       } 
       else if(req.url == '/auth/facebook'){ 
        passport.authenticate('facebook'); 
        return; 
       } 
       else if(req.url == '/auth/facebook/callback'){ 
        passport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'}); 
        return; 
       } 
       if(folder){ 
        console.log('got to folder part\n\n'); 
        fs.readFile(folder, function(error, content){ 
         if(error){ 
         res.writeHead(500); 
         res.end(); 
         } 
         else{ 
         res.writeHead(200, {'Content-Type': contentType}); 
         res.end(content); 
         } 
        }); 
        } 
        else{ res.writeHead(500); res.end();} 
      } 
      else {res.writeHead(500); res.end();} 
     } 
    } 

    connect.createServer(
    connect.cookieParser(), 
    connect.bodyParser(), 
    connect.session({secret:'wakajakamadaka'}), 
    passport.initialize(), 
    passport.session(), 
    checkLoggedIn).listen(8888); 
    console.log('Server has started.'); 
} 

Hat jemand einen Ratschlag oder sieht einen Fehler in dem, was ich mache? Meine anderen beiden Alternativen sind, zu jedem Autohandy zurückzukehren und herauszufinden, was dort vor sich geht, oder zu ExpressJS zu wechseln, aber ich möchte lieber nicht mit einer dieser Optionen gehen.

Best,
Sami

Antwort

8

passport.authenticate gibt eine Funktion, die typischerweise in der Middleware-Kette verwendet wird, die mit req und res von Express aufgerufen wird.

Es wird eigenständige innerhalb anderer Middleware arbeiten oder einer Route-Handler, wie Ihre checkLoggedIn Funktion, aber Sie müssen explizit die Funktion mit req, res kehrte aufrufen und next es die Anforderung verarbeiten zu lassen.

else if(req.url == '/auth/facebook'){ 
    // NOTE: call the function returned to process the request 
    passport.authenticate('facebook')(req, res, next); 
    return; 
} 

Sieht gut aus sonst. Lass es mich wissen, wenn das dich aufmischt.


UPDATE

Jared hat mich ein wenig außerhalb von Stackoverflow geholfen, und wir haben das Problem vollständig herausgefunden. Ich aktualisiere diese Antwort mit den neuen Informationen, die wir gefunden haben.


1) Ein Problem ist klar, dass die Umleitung() Middleware in Express existiert aber nicht in Verbindung (zumindest nicht in der aktuellen Version). Wenn eine Verbindung verwenden, müssen Sie von return res.redirect(options.successRedirect); auf Linie 97 von authenticate.js im PassportJS Modul ändern:

var redirect = function(redirectionURL){ 
    res.writeHead(302, {'location':redirectionURL}); 
    res.end();    
} 

return redirect(options.successRedirect); 

note - die options.successRedirect über die gleiche wie die successRedirect im Funktionscode Rückruf ist. Dies wäre die Zeile passport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'}); im Code in meiner Frage.


2) Die andere ist, dass ich das Cluster-Modul in meiner app (nicht etwas, bin mit, die oben in meinem Code-Schnipsel zeigt). Dies bedeutet, dass Sitzungsdaten von der nodeJS-App nicht richtig gelesen werden, was zu meinen Problemen führte. Dieses Problem betrifft alle Bibliotheken, die Sitzungen verwenden, einschließlich aller anderen Authentifizierungsmodule, die Sitzungen verwenden (z. B. eachauth, connect-auth usw.)) werde ich Jared für eine Lösung zitieren:

Quick reply: are you using cluster or spinning up multiple server instances?

If so, the built-in MemoryStore for the session won't work properly, and you need to switch to something like this: https://github.com/visionmedia/connect-redis

Or one of the other session stores listed here: https://github.com/senchalabs/connect/wiki

The reason is that you'll end up hitting a server which didn't serve the original request, and thus doesn't have that session information in its own memory. That sounds like what could be going on if deserializeUser isn't called 100% of the time.

hoffe, das hilft wer es hier macht!

+0

hmm ich komme weiter, als ich vorher war, aber es funktioniert noch nicht ganz. Jetzt registriere ich den Rückruf von Facebook. Ich überprüfe jetzt '/ auth/facebook/callback' gegen req.url.split ('?') [0], damit der Callback registriert wird. Das Hinzufügen von a (req, res, next) nach dem Funktionsaufruf verursacht eine unendliche Umleitungsschleife. irgendwelche Ideen? – thisissami

+0

Ich denke, Sie müssen 'connect.query()' Middleware in Ihrem 'createServer' Middleware-Setup verwenden. Passport erwartet, dass "req.query" in vielen Fällen ausgefüllt wird, einschließlich des Erhalts des Autorisierungscodes im Facebook-Rückruf. –

+0

fast da ... mit einem '(req, res, next)' am Ende des Callback-Authentifizierungsaufrufs wird die Facebook-Response-Funktion mit den entsprechenden Facebook-Daten erreicht. Allerdings bekomme ich einen 'TypeError: Object # hat keine Methode 'redirect'. Die problematische Codezeile lautet 'return res.redirect (options.successRedirect);' in Zeile 97 von authenticate.js. Irgendeine Idee, was das Problem sein könnte? – thisissami