A Comprehensive Guide to Local Authentication with Passport.js in Express
Authentication is a fundamental aspect of web applications, enabling secure user access and personalized experiences. In this guide, we’ll walk through the complete setup of local authentication in a Node.js and Express application using Passport.js.
📌 What is Passport.js?
Passport.js is a flexible and modular authentication middleware for Node.js. It supports multiple authentication strategies, including local authentication (username/password), OAuth providers (Google, Facebook), and even JWT authentication.
🚀 Setting Up the Express Server
Before we begin, ensure you have Node.js installed. You can check this by running:
node -v
1️⃣ Install Dependencies
Run the following command to install the required packages:
npm init -y # Initialize a Node.js project npm install express passport passport-local express-session connect-flash
express: Web framework for Node.js
passport: Authentication middleware
passport-local: Strategy for username/password authentication
express-session: Session management for authentication
connect-flash: Flash messages for displaying login errors
2️⃣ Create the Server (server.js)
const express = require('express'); const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const session = require('express-session'); const flash = require('connect-flash'); const users = [ { id: 1, username: 'alice', password: 'secret', role: 'admin' }, { id: 2, username: 'bob', password: 'password', role: 'user' } ]; const findUser = (username) => users.find(user => user.username === username); const app = express(); // Middleware Configuration app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(session({ secret: 'supersecretkey', resave: false, saveUninitialized: false })); app.use(flash()); app.use(passport.initialize()); app.use(passport.session());
3️⃣ Configure Passport Local Strategy
Passport needs to be set up with a strategy for authenticating users. The LocalStrategy validates the username and password:
passport.use(new LocalStrategy( (username, password, done) => { const user = findUser(username); if (!user) return done(null, false, { message: 'User not found' }); if (password !== user.password) return done(null, false, { message: 'Incorrect password' }); return done(null, user); } ));
findUser(username)
: Searches for a user in the database (mocked with an array).done(null, false, { message })
: Sends error messages when authentication fails.
4️⃣ Serialize and Deserialize User Sessions
To maintain authentication across requests, Passport serializes user information into a session and deserializes it upon subsequent requests:
passport.serializeUser((user, done) => done(null, user.id)); passport.deserializeUser((id, done) => done(null, users.find(user => user.id === id)));
5️⃣ Middleware to Protect Routes
To prevent unauthorized access, we create a middleware function to check if a user is authenticated:
function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) return next(); res.redirect('/login'); }
6️⃣ Define Routes for Login and Authentication
We create a login page where users can input their credentials:
app.get('/login', (req, res) => { const errorMessage = req.flash('error'); res.send(` <h2>Login</h2> ${errorMessage.length ? `<p style="color: red;">${errorMessage[0]}</p>` : ''} <form method="post" action="/login"> <div><label>Username:</label> <input type="text" name="username"/></div> <div><label>Password:</label> <input type="password" name="password"/></div> <button type="submit">Login</button> </form> `); });
Then, we handle authentication using Passport:
app.post('/login', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login', failureFlash: true }) );
7️⃣ Protect Profile Route
The /profile
route should be accessible only to logged-in users:
app.get('/profile', ensureAuthenticated, (req, res) => { res.send(`<h2>Welcome, ${req.user.username}!</h2>`); });
8️⃣ Start the Server
Finally, start the server:
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
🔥 How It Works
User visits /login and enters credentials.
Passport.js checks credentials using the LocalStrategy.
If successful, the user is redirected to /profile.
If authentication fails, an error message is shown.
Authenticated users can access the protected /profile route.
🎯 Conclusion
By following these steps, we have successfully implemented local authentication using Passport.js in an Express.js application. This setup provides a secure and scalable foundation for handling user authentication.
🚀 What’s next? Try adding Google OAuth authentication to your project! Let me know in the comments if you want a tutorial on that. Happy coding! 🎉
Top comments (1)
Nice intro. I recently implemented a full-stack passport.js demo on Stackblitz, so easy to share and build further, but slighly more focused on the front-end and reactive streams.
OAuth sounds like a great next step, actually... time to make OAuth simple to add everywhere, isn't it? Collab?