passport.js middleware passport.initialize () non in uso


103

Sto usando node con express + mongoose e sto provando a usare passport.js con api riposante.
Continuo a ricevere questa eccezione dopo il successo dell'autenticazione (vedo l'URL di richiamata sul 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

Ho letto che avrei dovuto mettere app.use(passport.initialize());e app.use(passport.session());prima app.use(app.router);e questo è quello che ho fatto. Ecco il mio express.js che registra i middleware:

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

Che c'è?

AGGIORNAMENTO Secondo @Peter Lyons ho cambiato l'ordine delle configurazioni nel seguente, ma ho ancora lo stesso errore:

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

Le versioni di Express 4.x non supportano alcuni metodi. Vedi github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Risposte:


206

Segui l'esempio per evitare l'inferno del middleware fuori servizio che Express rende così facile l'accesso. Direttamente dai documenti. Nota come il tuo non corrisponde esattamente a questo.

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

Documenti

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

tu

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

L'ho cambiato in quello che suggerisci ma genera ancora questo errore. Ho aggiornato la mia domanda con il nuovo file express.js /
Naor

7
Quindi il codice che hai qui non è il tuo codice di primo livello. In precedenza nel programma si stanno facendo tutte le chiamate a app.get, app.postecc? Ciò farà sì che il router venga aggiunto allo stack prima di quanto intendi. Mostraci TUTTO il codice rivelatore che inizia con quando invoca la express()funzione per ottenere il tuo appoggetto. Questa è la mia seconda ipotesi.
Peter Lyons

3
Ho notato che app.use (app.router); viene chiamato dopo l'inizializzazione del passport ma io chiamo: require ('./ config / routes') (app, passport, auth); prima di chiamare per esprimere le configurazioni. Il passaggio da una riga all'altra ha risolto il problema. Grazie!
Naor

1
Questo ha funzionato per me! Ma perché il middleware deve essere in questo ordine?
Anthony al

3
In base alla progettazione in modo da poter fare affidamento sui prerequisiti. La sessione non funzionerà se cookieParser non ha ancora analizzato i cookie.
Peter Lyons

12

Nel mio caso (stesso messaggio di errore) ho dimenticato di aggiungere le inizializzazioni del passaporto:

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

AGGIORNAMENTO: Funzionando solo fino alla versione Express 3, la versione 4 non supporta più app.configure ()


1
App.configure non può più essere utilizzato. github.com/strongloop/express/wiki/… .. Dovrebbero aggiornare i documenti del passaporto. giusto?
jack blank

9

Nel mio caso l'errore era dovuto al fatto che stavo cercando di promettere req.loginsenza vincolarlo , quindi quando la funzione è stata chiamata non è riuscita thisa reqtrovare le passportimpostazioni. La soluzione è vincolante req.login.bind(req)prima di passarla a promisifyse stai usando Node v8.


E questo "problema di ambito" si verifica, ad esempio, quando si utilizzano argomenti che destrutturano come function({ login })passare il reqprimo argomento. La tua soluzione ha funzionato per me, grazie
Manuel Di Iorio

Sì, è come thisfunziona in Javascript. Se non chiami la funzione come metodo oggetto, allora thissarà undefined(o windownel browser)
Jiayi Hu

Suggerimento per chiunque legga questa risposta e non capire ... se si indaga Function.prototype.call, Function.prototype.applycome thisopere in JavaScript ed i principi alla base dell'eredità prototipo, si promuoverà al livello di Javascript Guru nel processo :)
Stijn de Witt

Saluti, speravo che sarebbe stato semplice comeutil.promisify(req.login.bind(req));
Julian H. Lam

4

Ciò che mi ha aiutato è stato anche mettere i percorsi DOPO la configurazione dei cookie :

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

hai idea del perché le route di inizializzazione dopo la configurazione funzionano?
Ishu

Questo ha risolto il mio problema. Ho spostato tutte le rotte, usa le chiamate dopo qualsiasi cosa relativa al passaporto.
Nick Van Brunt

2

La risposta di Peter Lyons mi ha aiutato a risolverlo, ma l'ho risolto in un modo un po 'diverso.

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

Dai un'occhiata al mio repository GitHub per l'intero codice e non solo per lo snippet di codice qui.


1

Nel mio caso (stesso messaggio di errore), stavo sviluppando una strategia personalizzata e non ho bisogno di utilizzare una sessione . Ho appena dimenticato di aggiungere session: falseil authenticatemiddleware del percorso .

  app.post('/api/public/auth/google-token',
    passport.authenticate('google-token', {
      session: false
    }),
    function (req: any, res) {
      res.send("hello");
    }
  );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.