Passport
Passport is an Express-compatible authentication middleware for Node.js. It provides a simple, unobtrusive way to authenticate requests through an extensible set of 'strategies' (plugins) for various authentication methods like username/password, OAuth, or OpenID. It focuses solely on authentication, allowing developers to make application-level decisions about database schemas and routing. The current stable version is 0.7.0, and it is actively maintained.
Common errors
-
Error: Passport is not initialized. To use Passport middleware, you must first call passport.initialize().
cause The `passport.initialize()` middleware was not added to the Express application.fixAdd `app.use(passport.initialize());` before any routes or other Passport middleware. -
Error: Failed to serialize user into session
cause The `passport.serializeUser` function was not defined or returned an invalid value.fixImplement `passport.serializeUser((user, done) => { done(null, user.id); });` (replace `user.id` with a unique identifier for your user). -
Error: Failed to deserialize user from session
cause The `passport.deserializeUser` function was not defined or failed to retrieve a user for the provided ID.fixImplement `passport.deserializeUser((id, done) => { /* find user by id from your database */ done(null, user); });` -
Error: Unknown authentication strategy "local"
cause The 'local' strategy (or any specified strategy) has not been registered with Passport using `passport.use()`.fixEnsure `passport.use(new LocalStrategy(...))` (or the equivalent for your chosen strategy) is called after importing the strategy and before `passport.authenticate()` is used. -
TypeError: Cannot read properties of undefined (reading 'username')
cause Attempting to access `req.user` when no user is authenticated or `deserializeUser` failed to populate `req.user`.fixEnsure the user is properly authenticated, `passport.deserializeUser` is correctly implemented and fetching a user, and check `req.isAuthenticated()` before accessing `req.user`.
Warnings
- gotcha Passport itself does not include any authentication logic or strategies. You must install and configure specific strategy packages (e.g., `passport-local`, `passport-google-oauth2`) separately for each authentication method you wish to use.
- gotcha For persistent login sessions, Passport requires a session middleware (like `express-session`) to be set up and integrated via `app.use(passport.initialize())` and `app.use(passport.session())`.
- gotcha You must implement `passport.serializeUser` and `passport.deserializeUser` functions for session management to work correctly. Without them, users cannot be stored in or retrieved from the session.
- gotcha The `passport.authenticate()` middleware requires a string argument specifying the name of the strategy to use (e.g., 'local'). This name must correspond to a strategy previously registered with `passport.use()`.
- gotcha Strategy callback functions (e.g., `LocalStrategy`'s `verify` function) must call the `done()` callback correctly to indicate success (`done(null, user)`), failure (`done(null, false)`), or an error (`done(err)`). Incorrect calls can lead to authentication issues or unhandled errors.
Install
-
npm install passport -
yarn add passport -
pnpm add passport
Imports
- passport
import passport from 'passport'
Quickstart
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import { Strategy as LocalStrategy } from 'passport-local';
const app = express();
// Mock User database (in-memory)
const users = [{ id: '1', username: 'testuser', password: 'password123' }];
// Configure Passport local strategy
passport.use(new LocalStrategy(
(username, password, done) => {
const user = users.find(u => u.username === username);
if (!user || user.password !== password) {
return done(null, false, { message: 'Incorrect username or password.' });
}
return done(null, user);
}
));
// Configure Passport session serialization/deserialization
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
const user = users.find(u => u.id === id);
done(null, user);
});
// Setup Express middleware
app.use(session({
secret: process.env.SESSION_SECRET ?? 'a-very-secret-key', // Use a strong secret in production
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.urlencoded({ extended: false })); // For form parsing
// Example routes
app.get('/login', (req, res) => {
res.send('<form action="/login" method="POST">Username: <input name="username"/><br/>Password: <input type="password" name="password"/><br/><button type="submit">Login</button></form>');
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/profile',
failureRedirect: '/login',
failureMessage: true
})
);
app.get('/profile', (req, res) => {
if (!req.isAuthenticated()) {
return res.redirect('/login');
}
res.send(`Welcome, ${req.user.username}! This is your profile.`);
});
app.listen(3000, () => console.log('Server running on port 3000'));
// To run this example:
// npm install express express-session passport passport-local
// Add "type": "module" to your package.json for ESM support.