Que fait le middleware de passeport.session ()?

125

Je construis un système d'authentification à l'aide de Passport.js à l'aide de l' authentification facile des nœuds: installation et tutoriel local .

Je ne sais pas ce que passport.session()ça fait.

Après avoir joué avec les différents middleware, j'ai compris que express.session()c'est ce qui envoie un identifiant de session via les cookies au client, mais je ne sais pas trop ce que passport.session()fait et pourquoi il est nécessaire en plus express.session().

Voici comment je configure mon application:

// Server.js configure l'application et configure le serveur Web

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var configDB = require('./config/database.js');

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);
Georges Krinker
la source

Réponses:

139

passport.session() agit comme un middleware pour modifier l'objet req et changer la valeur «utilisateur» qui est actuellement l'identifiant de session (du cookie client) en véritable objet utilisateur désérialisé.

Alors que les autres réponses apportent quelques bons points, j'ai pensé que des détails plus spécifiques pourraient être fournis.

app.use(passport.session());

est équivalent à

app.use(passport.authenticate('session'));

Où «session» se réfère à la stratégie suivante qui est fournie avec passeportJS.

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

Plus précisément, lignes 59-60:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

Où il agit essentiellement comme un middleware et modifie la valeur de la propriété 'user' dans l'objet req pour contenir l'identité désérialisée de l'utilisateur. Pour que cela fonctionne correctement, vous devez inclure serializeUseret des deserializeUserfonctions dans votre code personnalisé.

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

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

Cela trouvera l'utilisateur correct dans la base de données et le passera en tant que variable de fermeture dans le rappel done(err,user);afin que le code ci-dessus dans le passport.session()puisse remplacer la valeur 'user' dans l'objet req et passer au middleware suivant dans la pile.

lindsaymacvean
la source
hé, comment puis-je stocker les détails des utilisateurs en session uniquement, je ne veux pas les stocker directement dans la base de données
Débutant
1
"dans les en-têtes de demande"? non juste dans l'objet de requête
caub
J'ai remarqué que si la stratégie de session est capable de restaurer l'authentification et de désérialiser l'utilisateur. Mais malgré cela, l'authentification passe toujours à la stratégie suivante, qui est l'authentification facebook dans mon scénario. Je me demande quel est l'intérêt de la stratégie de session si elle continue à invoquer les stratégies suivantes même lorsque la session est capable de récupérer l'utilisateur.
nishant
15

De la documentation

Dans une application basée sur Connect ou Express, le middleware passeport.initialize () est requis pour initialiser Passport. Si votre application utilise des sessions de connexion persistantes, le middleware passeport.session () doit également être utilisé.

et

Séances

Dans une application Web classique, les informations d'identification utilisées pour authentifier un utilisateur ne seront transmises que lors de la demande de connexion. Si l'authentification réussit, une session sera établie et maintenue via un cookie défini dans le navigateur de l'utilisateur.

Chaque demande ultérieure ne contiendra pas d'informations d'identification, mais plutôt le cookie unique qui identifie la session. Afin de prendre en charge les sessions de connexion, Passport sérialisera et désérialisera les instances utilisateur vers et depuis la session.

et

Notez que l'activation de la prise en charge de session est entièrement facultative, bien qu'elle soit recommandée pour la plupart des applications. Si activé, assurez-vous d'utiliser express.session () avant passeport.session () pour vous assurer que la session de connexion est restaurée dans le bon ordre.

Josh C.
la source
1
Merci pour votre réponse rapide mais cela ne répond pas à ma question. Notez également que si vous avez une application express et utilisez express.session (), sur tout client qui se connecte à votre serveur express (qu'il soit authentifié ou non), il recevra une session via un cookie. Cela est indépendant du fait qu'il se trouve ou non dans une page protégée par connexion de votre application. Je voudrais toujours connaître la différence entre les deux middleware.
Georges Krinker
1
@GeorgesKrinker ce sont les méthodes serializeUser () et deserializeUser. L'intergiciel express restaurera les informations de session, mais ce n'est pas nécessairement lié à la façon dont passeport gère les informations de l'utilisateur. Cela doit être fait après que la séance soit réhydratée par express.
Josh C.
Eh bien, j'avais l'impression que les méthodes serializeUser () et deserializeUser fonctionnaient sur authenticate () dans les routes.
Georges Krinker
@GeorgesKrinker Je ne pense pas. Lorsque j'ai utilisé le passeport, je n'ai appelé .authenticate que lors de la connexion.
Josh C.
app.post('/login', passport.authenticate('local'), ...
Josh C.
11

Bien que vous utilisiez PassportJspour valider l'utilisateur dans le cadre de votre URL de connexion, vous avez toujours besoin d'un mécanisme pour stocker ces informations utilisateur dans la session et les récupérer à chaque demande ultérieure (c'est-à-dire sérialiser / désérialiser l'utilisateur).

Donc, en fait, vous authentifiez l'utilisateur à chaque demande, même si cette authentification n'a pas besoin de rechercher une base de données ou un oauth comme dans la réponse de connexion. Le passeport traitera donc l'authentification de session comme une autre stratégie d'authentification.

Et pour utiliser cette stratégie - qui est nommée session, il suffit d'utiliser un simple raccourci - app.use(passport.session()). Notez également que cette stratégie particulière voudra que vous implémentiez des fonctions de sérialisation et de désérialisation pour des raisons évidentes.

uniwalker
la source
11

Il authentifie simplement la session (qui est remplie par express.session()). C'est équivalent à:

passport.authenticate('session');

comme on peut le voir dans le code ici:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233

Jared Hanson
la source
6
Que voulez-vous dire? Il est exécuté à chaque demande et n'a pas nécessairement d'informations d'identification pour s'authentifier. Pourriez-vous me donner un peu plus de détails sur le flux de travail qui se produit à chaque demande?
Georges Krinker
6
Oui, son exécution à chaque demande. L'ID de session généré par Express est un ID unique qui équivaut à peu près à un jeton d'authentification que le navigateur envoie à chaque demande. Les données stockées dans cette session sont utilisées pour restaurer l'état d'authentification de l'utilisateur.
Jared Hanson
Bonjour @JaredHanson Pourriez-vous jeter un oeil à ceci . Je n'ai trouvé la réponse nulle part?
Saras Arya
@JaredHanson J'essaie d'utiliser passeport.js pour m'authentifier auprès d'un serveur d'autorisation open source largement utilisé et conforme à OAuth2. Mais j'obtiens une erreur. Êtes-vous prêt à aider à résoudre le problème? Voici le lien: stackoverflow.com/questions/38176236/…
DollarCoffee
@JaredHanson: Ce que j'observe, c'est que l'objet req augmenté des informations de passeport.user juste après la connexion via google-oauth, est perdu lorsque la prochaine demande de nouvelle page est effectuée sur le site. Est-ce un comportement attendu? Alors je ne sais pas comment récupérer les informations de l'utilisateur récemment connecté?
user1102171