passeport.js passeport.initialize () middleware non utilisé

104

J'utilise node avec express + mongoose et j'essaie d'utiliser passeport.js avec une api reposante.
Je continue à recevoir cette exception après le succès de l'authentification (je vois l'URL de rappel sur le navigateur):

/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

J'ai lu que je devrais mettre app.use(passport.initialize());et app.use(passport.session());avant app.use(app.router);et c'est ce que j'ai fait. Voici mon express.js qui enregistre les middlewares:

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

Qu'est-ce qui ne va pas?

MISE À JOUR Selon @Peter Lyons, j'ai changé l'ordre des configurations comme suit, mais j'ai toujours la même erreur:

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
la source
Les versions Express 4.x ne prennent pas en charge certaines méthodes. Voir github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x
miksiii

Réponses:

207

Suivez l'exemple pour éviter l'enfer du middleware hors service qu'express facilite l'accès. Directement de la documentation. Notez que le vôtre ne correspond pas exactement à cela.

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. passeport.initialiser
  4. passeport.session
  5. app.router

Tu

  1. passeport.initialiser
  2. passeport.session
  3. cookieParser
  4. session
  5. app.router
Peter Lyons
la source
Je l'ai changé pour ce que vous suggérez, mais cela génère toujours cette erreur. J'ai mis à jour ma question avec le nouveau fichier express.js /
Naor
7
Le code que vous avez ici n'est donc pas votre code de premier niveau. Plus tôt dans votre programme vous faites des appels à app.get, app.postetc? Ceux-ci entraîneront l'ajout du routeur à la pile plus tôt que prévu. Montrez-nous TOUS le code révélateur en commençant par lorsque vous appelez la express()fonction pour obtenir votre appobjet. C'est ma deuxième hypothèse.
Peter Lyons
3
J'ai remarqué que app.use (app.router); est appelé après l'initialisation du passeport mais j'appelle: require ('./ config / routes') (app, passeport, auth); avant d'appeler pour exprimer des configurations. La commutation entre les deux lignes a résolu le problème. Merci!
Naor
1
Cela a fonctionné pour moi! Mais pourquoi le middleware doit-il être en ordre comme ça?
Anthony au
3
De par sa conception, vous pouvez vous fier à la réalisation des conditions préalables. La session ne fonctionnera pas si cookieParser n'a pas encore analysé les cookies.
Peter Lyons
12

Dans mon cas (même message d'erreur), j'ai oublié du tout d'ajouter les initialisations du passeport:

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

MISE À JOUR: Ne fonctionne que jusqu'à la version express 3, la version 4 ne prend plus en charge app.configure ()

Matthias M
la source
1
App.configure ne peut plus être utilisé. github.com/strongloop/express/wiki/… .. Ils devraient mettre à jour les documents sur les passeports. droite?
jack blank
9

Dans mon cas , l'erreur a été parce que je tente de promisify req.loginsans se lier thisà req, alors quand la fonction a été appelée il ne pouvait pas trouver les passportparamètres. La solution est contraignante req.login.bind(req)avant de la transmettre promisifysi vous utilisez Node v8.

Jiayi Hu
la source
Et ce "problème de portée" se produit par exemple lorsque vous utilisez des arguments de déstructuration comme function({ login })passer le reqcomme premier argument. Votre solution a fonctionné pour moi, merci
Manuel Di Iorio
Oui, c'est ainsi que thisfonctionne en Javascript. Si vous n'appelez pas la fonction en tant que méthode objet, le thissera undefined(ou windowdans le navigateur)
Jiayi Hu
Astuce pour toute personne lisant cette réponse et ne pas comprendre ... si vous enquêtez Function.prototype.call, Function.prototype.applycomment thisfonctionne en Javascript et les principes derrière l' héritage prototypique, vous ferez la promotion au niveau de Javascript Guru dans le processus :)
Stijn de Witt
Salut, j'espérais que ce serait aussi simple queutil.promisify(req.login.bind(req));
Julian
4

Ce qui m'a aidé aussi, c'est de mettre des routes APRÈS la configuration des cookies :

// 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
la source
Vous avez une idée de la raison pour laquelle les routes init après la configuration fonctionnent?
Ishu
Cela a résolu mon problème. J'ai déplacé toutes les routes.Utilisez les appels après tout ce qui concerne le passeport.
Nick Van Brunt le
2

La réponse de Peter Lyons m'a aidé à le résoudre, mais je l'ai résolu d'une manière un peu différente.

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

Jetez un œil à mon dépôt GitHub pour tout le code et pas seulement l'extrait de code ici.

Isak La Fleur
la source
1

Dans mon cas (même message d'erreur), je développais une stratégie personnalisée et je n'ai pas besoin d'utiliser une session . J'ai juste oublié d'ajouter session: falsedans mon authenticatemiddleware de route .

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

Placez le app.use(passport.initialize())middleware devant le middleware app.routeret cela fonctionne comme un charme

Sai kiran Kavali
la source