Home » Nodejs » When Serialize and Deserialize call in passport js

When Serialize and Deserialize call in passport js

Posted by: admin November 29, 2017 Leave a comment

Questions:

I have to know when Serialize and Deserialize called. For testing i have put alert(user.id) but no action happened. I have some queries are:-

  • from where user object has received in passport.serializeUser(function(user, done){...
  • what role play process.nextTick() here
  • how to call callback function i.e, function(req, email, password, done), if send multiple form values e.g(name,email,password,address,mobile).

Here is code:-

 //config/passport.js

var LocalStrategy   = require('passport-local').Strategy;

var User            = require('../app/models/user');

module.exports = function(passport) {

    passport.serializeUser(function(user, done) {
        alert(user.id);//// Here is my testing alert
        done(null, user.id);
    });

    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });


passport.use('local-signup', new LocalStrategy({
        usernameField : 'email',
        passwordField : 'password',
        passReqToCallback : true 
    },
    function(req, email, password, done) {
       process.nextTick(function() {
        User.findOne({ 'local.email' :  email }, function(err, user) {

            if (err)
                return done(err);

            if (user) {
                return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
            } else {
                var newUser            = new User();
                newUser.local.email    = email;
                newUser.local.password = newUser.generateHash(password);
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
            }

        });    

        });

    }));
}
Answers:

Based on my knowledge of using Passport.js for a project, I will try to answer as much as I can.

First of all, there is nothing (function) like alert() in nodejs, so you would have to rename your alert(...) which is a browser thing, to something like console.log(...)

I cannot see your app.js file so, I will go ahead and try to answer your queries based on my experience of using passportjs.

Assuming that you have following in your app.js (order is important, see here)

var passport = require('passport');
// express-session configs here
// following is invoked on each request.
app.use(passport.initialize());

passport.initialize() and passport.session() are invoked on each request and they are the ones that cause serializeUser to load the user id to req.user if a serialized user is found in the server (when using mongodb, if the user exist in mongodb).

passport.session() calls deserializeUser on each request, which queries the mongodb using the user._id that was initially loaded to req.user by serializeUser and stores the more information about user in the req.user.

process.nextTick() defers the execution of the callback until the next pass around the event loop. Database querying is sync in nature and process.nextTick() make it asynchronous. There is lots of tutorials about this, Google it.

As mentioned earlier, app.use(passport.session()) runs deserializeUser on each request (basically every request – if you list your express static path configs after passport.session() then even for requests that load static files). In my case, I needed authentication on specific routes and I wanted to do the authentication, deserializeUser etc to occur only when the user accesses a secure path hence, I had to put a condition to invoke passport.session() only when the path matched certain pattern as follow:

app.use(function(req, res, next){
  if(req.url.match('/xxxx/secure'))
    passport.session()(req, res, next)
  else
    next(); // do not invoke passport
});

Replacing app.use(passport.session()) with above helped. Now only when the user access secure paths, the passport process is invoked including serializeUser and deserializeUser. I am not sure if above is the perfect solution but, it greatly helps in reducing the amount of unnecessary querying of mongodb for user (deserializeUser).

Not sure what you are asking in your last point. There are quite a few tutorials that shows how to implement passportjs for local as well as social auth. You should have a look around.

MORE READING

For more interesting facts on how the session is loaded with user, read my answer in this SO question. It describes what Express does? what PassportJS does? and you will understand the the workflow easily (documentation makes it confusing and ambiguous).

Questions:
Answers:

Your 3rd point is

How to call callback function

function(req, email, password, done), if send multiple form values e.g(name,email,password,address,mobile).

As per my understanding,4th argument takes as a call back function.you can not use like and throw error

 function(req, email, password, mobile, address, done)

Questions:
Answers:

Serialization happens when you authenticate a user:

app.post('/login',
    passport.authenticate('local'),
        function(req, res) {
        // If this function gets called, authentication was successful.
        // `req.user` contains the authenticated user.
        res.redirect('/users/' + req.user.username);
});

Please find this code in you project and check if it looks like above and not like below:

passport.authenticate('local', { session: false })

Also please check does your project use sessions. See Sessions in official docs.