Episode 15 of 21

Serializing Users

Serialize and deserialize users for session management — tell Passport how to store the user in a cookie and how to retrieve them on subsequent requests.

Serializing Users

After done(null, user) is called in the Passport callback, Passport needs to know how to store the user in a session (serialize) and how to retrieve the user from a session (deserialize) on subsequent requests.

What Is Serialization?

Login:
User object → serialize → Store a small piece (user ID) in the cookie

Subsequent requests:
Cookie arrives → deserialize → Look up the full user object from the ID

You do not store the entire user object in the cookie — just the ID. On each request, Passport uses the ID to look up the full user from the database.

serializeUser

// config/passport-setup.js
passport.serializeUser(function(user, done) {
    done(null, user.id); // Save the MongoDB _id to the session
});

This runs after login. It takes the user object and determines what to store in the cookie — just the user.id (MongoDB's _id).

deserializeUser

passport.deserializeUser(function(id, done) {
    User.findById(id).then(function(user) {
        done(null, user); // Attach the full user object to req.user
    });
});

This runs on every request. It takes the ID from the cookie and finds the full user in the database. The user object is then attached to req.user.

The Flow

Login:
1. Google authenticates user
2. Passport callback fires → done(null, user)
3. serializeUser → stores user.id in session cookie
4. Cookie is sent to browser

Subsequent requests:
1. Browser sends cookie with user.id
2. deserializeUser → finds user by ID in MongoDB
3. User object attached to req.user
4. Route handler can access req.user

Complete passport-setup.js

const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const keys = require('./keys');
const User = require('../models/user-model');

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

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

passport.use(
    new GoogleStrategy({ /* ... */ }, function(accessToken, refreshToken, profile, done) {
        // Save or retrieve user...
    })
);

Key Takeaways

  • serializeUser determines what to store in the cookie — typically the user ID
  • deserializeUser uses the stored ID to retrieve the full user from the database
  • The user object is attached to req.user on every authenticated request
  • Only the ID travels in the cookie — keeping it small and secure