2. PassportJS
Passport.js is a flexible authentication middleware for Node.js that supports many strategies like local username/password, Google, Facebook, JWT, etc. Hereβs a basic setup using the local strategy for both authentication and authorization.
β 1. Passport (Local Strategy)
1.1 Example 01
Absolutely! Hereβs a simple and complete example of using passport.js
for local authentication (username & password login) with Express.js.
π§ Tech Stack
express
passport
passport-local
express-session
bcrypt
(for password hashing)
π File Structure
.βββ app.jsβββ users.js (in-memory fake DB)
1. π¦ Install Dependencies
npm install express passport passport-local express-session bcrypt
2. π Simple in-memory user βdatabaseβ
const bcrypt = require('bcrypt');
const users = [];
async function addUser(username, password) { const hashed = await bcrypt.hash(password, 10); users.push({ id: Date.now().toString(), username, password: hashed });}
function findUser(username) { return users.find(user => user.username === username);}
module.exports = { users, addUser, findUser };
3. π Main Express App with Passport Setup
const express = require('express');const session = require('express-session');const passport = require('passport');const LocalStrategy = require('passport-local').Strategy;const bcrypt = require('bcrypt');const { users, addUser, findUser } = require('./users');
const app = express();app.use(express.urlencoded({ extended: false }));
// Session middlewareapp.use(session({ secret: 'secret-key', resave: false, saveUninitialized: false}));
// Passport initializationapp.use(passport.initialize());app.use(passport.session());
// Configure Passport strategypassport.use(new LocalStrategy(async (username, password, done) => { const user = findUser(username); if (!user) return done(null, false, { message: 'User not found' });
const match = await bcrypt.compare(password, user.password); if (!match) return done(null, false, { message: 'Wrong password' });
return done(null, user);}));
passport.serializeUser((user, done) => { done(null, user.id);});
passport.deserializeUser((id, done) => { const user = users.find(u => u.id === id); done(null, user);});
// Routesapp.get('/', (req, res) => { res.send(`<h1>Home</h1> ${req.isAuthenticated() ? `<p>Welcome ${req.user.username}</p><a href="/logout">Logout</a>` : '<a href="/login">Login</a>'} `);});
app.get('/login', (req, res) => { res.send(` <h2>Login</h2> <form method="POST" action="/login"> <input name="username" placeholder="Username" required> <input name="password" placeholder="Password" type="password" required> <button type="submit">Login</button> </form> `);});
app.post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login'}));
app.get('/logout', (req, res) => { req.logout(() => { res.redirect('/'); });});
// Create a sample useraddUser('admin', 'password123').then(() => { app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });});
β How it Works
passport-local
checks the username and password.- If valid, Passport serializes the user to the session.
- Authenticated users can now be recognized via
req.isAuthenticated()
andreq.user
.
π Try It Out
- Go to http://localhost:3000
- Login with:
Username: adminPassword: password123
- Youβll see a welcome message after logging in!
1.2 Example 02
1. Install dependencies
npm install passport passport-local express-session bcrypt
2. Set up your user model
Assume youβre using something like this (in-memory user example for simplicity):
const users = [ { id: 1, username: 'admin', passwordHash: '$2b$10$....', role: 'admin' }];
Use bcrypt
to hash passwords.
3. Configure Passport
const LocalStrategy = require('passport-local').Strategy;const bcrypt = require('bcrypt');
function initialize(passport, getUserByUsername, getUserById) { passport.use(new LocalStrategy(async (username, password, done) => { const user = getUserByUsername(username); if (!user) return done(null, false, { message: 'No user found' });
try { if (await bcrypt.compare(password, user.passwordHash)) { return done(null, user); } else { return done(null, false, { message: 'Incorrect password' }); } } catch (e) { return done(e); } }));
passport.serializeUser((user, done) => done(null, user.id)); passport.deserializeUser((id, done) => { const user = getUserById(id); done(null, user); });}
module.exports = initialize;
4. Set up Express App
const express = require('express');const session = require('express-session');const passport = require('passport');const initializePassport = require('./passport-config');const app = express();
// Dummy user methodsconst users = [...];const getUserByUsername = username => users.find(u => u.username === username);const getUserById = id => users.find(u => u.id === id);
initializePassport(passport, getUserByUsername, getUserById);
app.use(express.urlencoded({ extended: false }));app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));app.use(passport.initialize());app.use(passport.session());
5. Authentication Route
app.post('/login', passport.authenticate('local', { successRedirect: '/dashboard', failureRedirect: '/login'}));
6. Authorization Middleware
function checkAuthenticated(req, res, next) { if (req.isAuthenticated()) return next(); res.redirect('/login');}
function checkRole(role) { return function (req, res, next) { if (req.user && req.user.role === role) return next(); res.status(403).send('Forbidden'); };}
7. Protected Route
app.get('/dashboard', checkAuthenticated, (req, res) => { res.send(`Hello ${req.user.username}`);});
app.get('/admin', checkAuthenticated, checkRole('admin'), (req, res) => { res.send('Welcome Admin');});
8. Logout
app.post('/logout', (req, res) => { req.logout(err => { if (err) return next(err); res.redirect('/login'); });});
β Summary
Feature | How Itβs Handled |
---|---|
Authentication | passport.authenticate() |
Authorization | Middleware based on req.user |
Sessions | express-session + serialize/deserialize |
1.3 Passport & Session Handling
These three middlewares in Express + Passport are essential for user authentication using sessions.
1. π app.use(session({ ... }))
π What it does:
Sets up session support in Express. This allows your server to store data for a user across multiple HTTP requests (like login state).
π§ Why itβs needed:
- Passport uses sessions to remember whether a user is logged in.
- Without this, every request would be stateless, and youβd have to re-login on every request.
βοΈ Config options:
secret
: used to sign the session ID cookie.resave: false
: donβt save session if nothing changed.saveUninitialized: false
: donβt save empty sessions.
2. π app.use(passport.initialize())
π What it does:
Initializes Passport. It sets up middleware to handle authentication requests (e.g., login via strategy like local, Google, etc).
π§ Why itβs needed:
- Passport needs to hook into Express to handle things like
req.login()
,passport.authenticate()
, etc. - Without this, Passport wonβt function at all.
3. π§³ app.use(passport.session())
π What it does:
Enables Passport session support β it integrates with express-session
to persist login state across requests.
π§ Why itβs needed:
- After login, Passport serializes the user into the session (using
serializeUser()
). - On every request, Passport automatically restores the user from the session (using
deserializeUser()
). - This enables
req.isAuthenticated()
andreq.user
to work.
4. π§© How they work together
-
Login β
passport.authenticate()
callsreq.login(user)
β storesuser.id
in the session. -
On future requests
express-session
loads the session from the cookie.passport.session()
deserializes the user intoreq.user
.
5. β Summary Table
Middleware | Purpose |
---|---|
express-session | Stores session cookie + session data |
passport.initialize() | Sets up Passport functionality |
passport.session() | Enables persistent login sessions |