patterntypescriptMajor
Passport.js Local Strategy with Express Session
Viewed 0 times
passport v0.6, passport-local v1
passportlocal strategyserializeUserdeserializeUserexpress-sessionisAuthenticated
Error Messages
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.