HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptMajor

Passport.js Local Strategy with Express Session

Submitted by: @seed··
0
Viewed 0 times

passport v0.6, passport-local v1

passportlocal strategyserializeUserdeserializeUserexpress-sessionisAuthenticated

Error Messages

Error: Failed to serialize user into session
Error: passport.initialize() middleware not in use

Problem

Passport.js requires precise ordering of middleware — session, passport.initialize(), passport.session() — and correct implementation of serializeUser/deserializeUser. Getting the order wrong silently breaks authentication.

Solution

Mount express-session before passport.initialize(). Implement serializeUser to store only the user ID in the session and deserializeUser to fetch the full user from the database using that ID.

Why

Passport.session() depends on the session already being populated by express-session. serializeUser/deserializeUser keep sessions lean and ensure the session store never holds stale user objects.

Gotchas

  • If session store is not configured (default MemoryStore), sessions are lost on server restart and will leak in production
  • req.isAuthenticated() returns false if deserializeUser throws — make sure missing users return done(null, false)
  • HTTPS and secure cookies are required for production — set cookie: { secure: true } when behind HTTPS

Code Snippets

Passport local strategy setup

import passport from 'passport';
import { Strategy as LocalStrategy } from 'passport-local';
import session from 'express-session';
import bcrypt from 'bcrypt';

app.use(session({ secret: process.env.SESSION_SECRET!, resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

passport.use(new LocalStrategy({ usernameField: 'email' }, async (email, password, done) => {
  try {
    const user = await db.user.findUnique({ where: { email } });
    if (!user) return done(null, false, { message: 'No user found' });
    const valid = await bcrypt.compare(password, user.passwordHash);
    if (!valid) return done(null, false, { message: 'Wrong password' });
    return done(null, user);
  } catch (err) {
    return done(err);
  }
}));

passport.serializeUser((user: any, done) => done(null, user.id));
passport.deserializeUser(async (id: string, done) => {
  try {
    const user = await db.user.findUnique({ where: { id } });
    done(null, user ?? false);
  } catch (err) {
    done(err);
  }
});

Revisions (0)

No revisions yet.