passport.js passport.initialize () Middleware wird nicht verwendet

103

Ich verwende Node mit Express + Mungo und versuche, passport.js mit erholsamer API zu verwenden.
Ich erhalte diese Ausnahme nach erfolgreicher Authentifizierung immer wieder (ich sehe die Rückruf-URL im Browser):

/Users/naorye/dev/naorye/myproj/node_modules/mongoose/lib/utils.js:419
        throw err;
              ^
Error: passport.initialize() middleware not in use
    at IncomingMessage.req.login.req.logIn (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/http/request.js:30:30)
    at Context.module.exports.delegate.success (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/middleware/authenticate.js:194:13)
    at Context.actions.success (/Users/naorye/dev/naorye/myproj/node_modules/passport/lib/passport/context/http/actions.js:21:25)
    at verified (/Users/naorye/dev/naorye/myproj/node_modules/passport-facebook/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth2.js:133:18)
    at Promise.module.exports.passport.use.GitHubStrategy.clientID (/Users/naorye/dev/naorye/myproj/config/passport.js:91:24)
    at Promise.onResolve (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
    at Promise.EventEmitter.emit (events.js:96:17)
    at Promise.emit (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
    at Promise.fulfill (/Users/naorye/dev/naorye/myproj/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20)
    at /Users/naorye/dev/naorye/myproj/node_modules/mongoose/lib/query.js:1822:13

Ich habe gelesen, dass ich app.use(passport.initialize());und app.use(passport.session());vorher setzen sollte und app.use(app.router);das habe ich getan. Hier ist meine express.js, die die Middleware registriert:

var express = require('express'),
    mongoStore = require('connect-mongo')(express),
    flash = require('connect-flash'),
    helpers = require('view-helpers');

module.exports = function (app, config, passport) {
    app.set('showStackError', true);
    // should be placed before express.static
    app.use(express.compress({
        filter: function (req, res) {
            return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
        },
        level: 9
    }));
    app.use(express.favicon());
    app.use(express.static(config.root + '/public'));

    app.use(express.logger('dev'));

    // set views path, template engine and default layout
    app.set('views', config.root + '/app/views');
    app.set('view engine', 'jade');

    app.configure(function () {
        // use passport session
        app.use(passport.initialize());
        app.use(passport.session());

        // dynamic helpers
        app.use(helpers(config.app.name));

        // cookieParser should be above session
        app.use(express.cookieParser());

        // bodyParser should be above methodOverride
        app.use(express.bodyParser());
        app.use(express.methodOverride());

        // express/mongo session storage
        app.use(express.session({
            secret: 'linkit',
            store: new mongoStore({
                url: config.db,
                collection : 'sessions'
            })
        }));

        // connect flash for flash messages
        app.use(flash());

        // routes should be at the last
        app.use(app.router);

        // assume "not found" in the error msgs
        // is a 404. this is somewhat silly, but
        // valid, you can do whatever you like, set
        // properties, use instanceof etc.
        app.use(function(err, req, res, next){
            // treat as 404
            if (~err.message.indexOf('not found')) {
                return next();
            }

            // log it
            console.error(err.stack);

            // error page
            res.status(500).render('500', { error: err.stack });
        });

        // assume 404 since no middleware responded
        app.use(function(req, res, next){
            res.status(404).render('404', {
                url: req.originalUrl,
                error: 'Not found'
            });
        });
    });
};

Was ist falsch?

UPDATE Laut @Peter Lyons habe ich die Konfigurationsreihenfolge wie folgt geändert, aber ich habe immer noch den gleichen Fehler erhalten:

var express = require('express'),
    mongoStore = require('connect-mongo')(express),
    flash = require('connect-flash'),
    helpers = require('view-helpers');

module.exports = function (app, config, passport) {
    app.set('showStackError', true);
    // should be placed before express.static
    app.use(express.compress({
        filter: function (req, res) {
            return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
        },
        level: 9
    }));
    app.use(express.favicon());
    app.use(express.static(config.root + '/public'));

    app.use(express.logger('dev'));

    // set views path, template engine and default layout
    app.set('views', config.root + '/app/views');
    app.set('view engine', 'jade');

    app.configure(function () {

        // dynamic helpers
        app.use(helpers(config.app.name));

        // cookieParser should be above session
        app.use(express.cookieParser());

        // bodyParser should be above methodOverride
        app.use(express.bodyParser());
        app.use(express.methodOverride());

        // express/mongo session storage
        app.use(express.session({
            secret: 'linkit',
            store: new mongoStore({
                url: config.db,
                collection : 'sessions'
            })
        }));

        // connect flash for flash messages
        app.use(flash());

        // use passport session
        app.use(passport.initialize());
        app.use(passport.session());

        // routes should be at the last
        app.use(app.router);

        // assume "not found" in the error msgs
        // is a 404. this is somewhat silly, but
        // valid, you can do whatever you like, set
        // properties, use instanceof etc.
        app.use(function(err, req, res, next){
            // treat as 404
            if (~err.message.indexOf('not found')) {
                return next();
            }

            // log it
            console.error(err.stack);

            // error page
            res.status(500).render('500', { error: err.stack });
        });

        // assume 404 since no middleware responded
        app.use(function(req, res, next){
            res.status(404).render('404', {
                url: req.originalUrl,
                error: 'Not found'
            });
        });
    });
};
Naor
quelle
Express 4.x-Versionen unterstützen einige Methoden nicht. Siehe github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Antworten:

206

Befolgen Sie das Beispiel, um die Middleware-Hölle zu vermeiden, die durch Express so einfach zu betreten ist. Direkt aus den Dokumenten. Beachten Sie, dass Ihre nicht genau dazu passt.

var app = express();
app.use(require('serve-static')(__dirname + '/../../public'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

Docs

  1. cookieParser
  2. Session
  3. passport.initialize
  4. passport.session
  5. app.router

Du

  1. passport.initialize
  2. passport.session
  3. cookieParser
  4. Session
  5. app.router
Peter Lyons
quelle
Ich habe es in das geändert, was Sie vorschlagen, aber es löst immer noch diesen Fehler aus. Ich habe meine Frage mit der neuen Datei express.js /
Naor
7
Der Code, den Sie hier haben, ist also nicht Ihr Code der obersten Ebene. Früher in Ihrem Programm machen Sie Anrufe an app.get, app.postetc? Dadurch wird der Router früher als beabsichtigt zum Stapel hinzugefügt. Zeigen Sie uns den gesamten offenbarenden Code, beginnend mit dem Aufrufen der express()Funktion zum Abrufen Ihres appObjekts. Das ist meine 2. Vermutung.
Peter Lyons
3
Ich habe bemerkt, dass app.use (app.router); wird nach der Passinitialisierung aufgerufen, aber ich rufe auf: require ('./ config / routen') (App, Pass, Auth); vor dem Aufruf, um Konfigurationen auszudrücken. Das Umschalten zwischen beiden Leitungen löste das Problem. Vielen Dank!
Naor
1
Das hat bei mir funktioniert! Aber warum muss die Middleware so in Ordnung sein?
Anthony bis
3
Sie können sich also darauf verlassen, dass die Voraussetzungen erfüllt sind. Die Sitzung funktioniert nicht, wenn cookieParser die Cookies noch nicht analysiert hat.
Peter Lyons
12

In meinem Fall (gleiche Fehlermeldung) habe ich vergessen, die Passinitialisierungen überhaupt hinzuzufügen:

app.configure(function () {
    ...
    app.use(passport.initialize());
    app.use(passport.session());
});

UPDATE: Nur bis Express Version 3, Version 4 unterstützt app.configure () nicht mehr

Matthias M.
quelle
1
App.configure kann nicht mehr verwendet werden. github.com/strongloop/express/wiki/… .. Sie sollten die Passdokumente aktualisieren. richtig?
Jack Blank
9

In meinem Fall lag der Fehler darin, dass ich versucht habe, req.loginohne Bindung thisan zu versprechen req, sodass beim Aufrufen der Funktion keine passportEinstellungen gefunden werden konnten. Die Lösung ist verbindlich, req.login.bind(req)bevor sie an promisifyNode v8 übergeben wird.

Jiayi Hu
quelle
Und dieses "Scope-Problem" tritt z. B. auf, wenn Sie Argumente verwenden, die die Strukturierung zerstören, wie das function({ login })Übergeben des reqersten Arguments. Ihre Lösung hat für mich funktioniert, danke
Manuel Di Iorio
Ja, so thisfunktioniert es in Javascript. Wenn Sie die Funktion nicht als Objektmethode aufrufen, thiswird undefined(oder windowim Browser)
Jiayi Hu
Tipp für alle, die diese Antwort lesen und nicht verstehen ... Wenn Sie untersuchen Function.prototype.call, Function.prototype.applywie thisJavascript funktioniert und welche Prinzipien hinter der prototypischen Vererbung stehen, werden Sie dabei auf die Ebene des Javascript Guru aufsteigen :)
Stijn de Witt
Prost, ich hatte gehofft, es wäre so einfach wieutil.promisify(req.login.bind(req));
Julian H. Lam
4

Was mir auch geholfen hat war, Routen NACH Cookies zu setzen config:

// init Cookies:
app.use(
    cookieSession({
        maxAge: 30 * 24 * 60 * 60 * 1000,
        keys: [keys.cookieKey]
    })
);
app.use(passport.initialize());
app.use(passport.session());

// init routes
const authRoutes = require("./routes/authRoutes")(app);
Michał Dobi Dobrzański
quelle
Haben Sie eine Idee, warum diese Init-Routen nach der Konfiguration funktionieren?
Ishu
Dies hat mein Problem behoben. Ich habe alle Routen verschoben. Verwenden Sie Anrufe nach irgendetwas Passbezogenem.
Nick Van Brunt
2

Die Antwort von Peter Lyons hat mir geholfen, es zu lösen, aber ich habe es auf eine etwas andere Art und Weise gelöst.

app.use(
  cookieSession({
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: [keys.cookieKey],
  }),
);
app.use(passport.initialize());
app.use(passport.session());

Schauen Sie sich mein GitHub-Repo für den gesamten Code und nicht nur das Code-Snippet hier an.

Isak La Fleur
quelle
1

In meinem Fall (gleiche Fehlermeldung) habe ich eine benutzerdefinierte Strategie entwickelt und muss keine Sitzung verwenden . Ich habe nur vergessen, session: falsemeine Route authenticateMiddleware hinzuzufügen .

  app.post('/api/public/auth/google-token',
    passport.authenticate('google-token', {
      session: false
    }),
    function (req: any, res) {
      res.send("hello");
    }
  );
ruwan800
quelle