Setting Up a Custom Authentication System with Node and Passport.js
Authentication is a fundamental part of any modern web application. Whether you’re building a personal project or a scalable SaaS platform, you need a system that securely verifies users and protects sensitive data. While there are many third-party authentication providers, sometimes you need more control. That’s where Passport.js shines.
Passport.js is a popular Node.js middleware that simplifies the process of adding authentication to your app. It supports a wide range of strategies (local, OAuth, JWT, etc.) and is flexible enough to fit custom logic and database integration.
This guide walks through how to set up a custom authentication system using Node.js, Express, and Passport.js, with a local strategy and session-based authentication.
Why Choose Passport.js?
- Modular: Use only the strategies you need
- Extensible: Customize how users are authenticated and stored
- Compatible: Works seamlessly with Express and other middleware
- Community-supported: Wide range of plugins and examples available
Project Setup
1. Install Dependencies
Create a new project and install the required packages:
npm init -y
npm install express passport passport-local express-session bcryptjs body-parser
2. File Structure
You can use a simple file structure like this:
/auth-app
├── server.js
├── auth/
│ ├── passport-config.js
└── users.js
Step-by-Step Implementation
1. Configure the Express App (server.js)
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const passport = require('passport');
const initializePassport = require('./auth/passport-config');
const users = require('./users');
const app = express();
initializePassport(passport);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: 'secret-key',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login'
}));
app.get('/dashboard', (req, res) => {
if (req.isAuthenticated()) {
res.send('Welcome to your dashboard!');
} else {
res.redirect('/login');
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
2. Create the Passport Config (auth/passport-config.js)
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const users = require('../users');
function initialize(passport) {
const authenticateUser = async (username, password, done) => {
const user = users.find(u => u.username === username);
if (!user) return done(null, false, { message: 'No user found' });
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, { message: 'Incorrect password' });
}
} catch (e) {
return done(e);
}
};
passport.use(new LocalStrategy(authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
const user = users.find(u => u.id === id);
return done(null, user);
});
}
module.exports = initialize;
3. Simulate a User Database (users.js)
const bcrypt = require('bcryptjs');
const users = [];
(async () => {
const hashedPassword = await bcrypt.hash('password123', 10);
users.push({ id: 1, username: 'johndoe', password: hashedPassword });
})();
module.exports = users;
This simulates a single user. In a production app, you’d use a real database (e.g., MongoDB, PostgreSQL).
Enhancing the System
Once the basic setup works, you can extend it with:
- User registration endpoint with email validation
- Flash messages for login errors
- Rate limiting and brute-force protection
- CSRF protection for sensitive requests
- JWT tokens for stateless authentication in APIs
- OAuth strategies (Google, GitHub, etc.) via
passport-google-oauth20or similar packages
Conclusion
By using Passport.js with Node.js and Express, you can build a custom authentication system that balances security, flexibility, and control. Whether you’re handling login sessions or planning to scale with tokens and social logins, Passport gives you a reliable foundation for managing user identity.
With a secure setup in place, you can now focus on building user features that truly matter , all while knowing that your app’s gatekeeping is solid.
Disclaimer
Article written with the help of AI.
Read the full Disclaimer HERE