What does passport.session() middleware do?

102,809

Solution 1

passport.session() acts as a middleware to alter the req object and change the 'user' value that is currently the session id (from the client cookie) into the true deserialized user object.

Whilst the other answers make some good points I thought that some more specific detail could be provided.

app.use(passport.session());

is equivalent to

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

Where 'session' refers to the following strategy that is bundled with passportJS.

Here's a link to the file: https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

And a permalink pointing to the following lines at the time of this writing:

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

Where it essentially acts as a middleware and alters the value of the 'user' property in the req object to contain the deserialized identity of the user. To allow this to work correctly you must include serializeUser and deserializeUser functions in your custom code.

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

This will find the correct user from the database and pass it as a closure variable into the callback done(err,user); so the above code in the passport.session() can replace the 'user' value in the req object and pass on to the next middleware in the pile.

Solution 2

From the documentation

In a Connect or Express-based application, passport.initialize() middleware is required to initialize Passport. If your application uses persistent login sessions, passport.session() middleware must also be used.

and

Sessions

In a typical web application, the credentials used to authenticate a user will only be transmitted during the login request. If authentication succeeds, a session will be established and maintained via a cookie set in the user's browser.

Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will serialize and deserialize user instances to and from the session.

and

Note that enabling session support is entirely optional, though it is recommended for most applications. If enabled, be sure to use express.session() before passport.session() to ensure that the login session is restored in the correct order.

Solution 3

It simply authenticates the session (which is populated by express.session()). It is equivalent to:

passport.authenticate('session');

as can be seen in the code here:

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

Solution 4

While you will be using PassportJs for validating the user as part of your login URL, you still need some mechanism to store this user information in the session and retrieve it with every subsequent request (i.e. serialize/deserialize the user).

So in effect, you are authenticating the user with every request, even though this authentication needn't look up a database or oauth as in the login response. So passport will treat session authentication also as yet another authentication strategy.

And to use this strategy - which is named session, just use a simple shortcut - app.use(passport.session()). Also note that this particular strategy will want you to implement serialize and deserialize functions for obvious reasons.

Share:
102,809

Related videos on Youtube

Georges Krinker
Author by

Georges Krinker

Updated on August 10, 2021

Comments

  • Georges Krinker
    Georges Krinker over 2 years

    I am building an authentication system using Passport.js using Easy Node Authentication: Setup and Local tutorial.

    I am confused about what passport.session() does.

    After playing around with the different middleware I came to understand that express.session() is what sends a session ID over cookies to the client, but I'm confused about what passport.session() does and why it is required in addition to express.session().

    Here is how I set up my application:

    // Server.js configures the application and sets up the webserver

    //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
    Georges Krinker about 10 years
    Thank you for your quick reply but that does not answer my question. Also, note that if you have an express application and use express.session(), on any client that connects to your express server (whether he is authenticated or not), he will be given a session via a cookie. That is independent on whether he is in a login protected page of your app or not. I still would like to know the difference between both middleware.
  • Josh C.
    Josh C. about 10 years
    @GeorgesKrinker it's the serializeUser() and deserializeUser methods. The express middleware will restore the session info, but that's not necessarily related to how passport is managing the user info. That has to be done after the session is rehydrated by express.
  • Georges Krinker
    Georges Krinker about 10 years
    Well I was under the impression that the serializeUser() and deserializeUser methods ran on authenticate() within the routes.
  • Josh C.
    Josh C. about 10 years
    @GeorgesKrinker I don't think so. When I used passport, I only called .authenticate on login.
  • Josh C.
    Josh C. about 10 years
    app.post('/login', passport.authenticate('local'), ...
  • Georges Krinker
    Georges Krinker about 10 years
    What do you mean? It's run on every request and doesn't necessarily have any credentials to authenticate. Would you mind giving me a little bit more details on the workflow that happens on each request?
  • Jared Hanson
    Jared Hanson about 10 years
    Yes, its run on every request. The session ID that is generated by Express, is a unique ID which is roughly equivalent to an authentication token that the browser sends with every request. The data stored in this session is used to restore the authentication state of the user.
  • Saras Arya
    Saras Arya over 8 years
    Hello @JaredHanson Could you take a look at this. I couldn't find the answer anywhere?
  • DollarCoffee
    DollarCoffee almost 8 years
    @JaredHanson I am trying to use passport.js to authenticate with a widely used open source authorization server which is OAuth2 compliant. But I am getting an error. Are you willing to help resolve the problem? Here is the link: stackoverflow.com/questions/38176236/…
  • Newbiee
    Newbiee over 7 years
    hey, how can i store user details in session only i dont want to store them in database dirctly
  • caub
    caub over 7 years
    "in the request headers" ? no just in the request object
  • user1102171
    user1102171 over 7 years
    @JaredHanson: What I observe is that the req object augmented with passport.user info just after login via google-oauth, is lost when the next request for a new page is done on the site. Is this expected behaviour ? Then I am at a loss of how to get back the recently logged in user info ?
  • nishant
    nishant over 5 years
    I have noticed that if the session strategy is able to restore the auth and deserialize the user. But despite that the authentication still moves to the next strategy, which is facebook auth in my scenario. I wonder what is the point of session strategy if it still continues to invoke the following strategies even when the session is able to recover the user.