DEV Community

A0mineTV
A0mineTV

Posted on

A Comprehensive Guide to Local Authentication with Passport.js in Express

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 
Enter fullscreen mode Exit fullscreen mode
  • 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()); 
Enter fullscreen mode Exit fullscreen mode

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); } )); 
Enter fullscreen mode Exit fullscreen mode
  • 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))); 
Enter fullscreen mode Exit fullscreen mode

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'); } 
Enter fullscreen mode Exit fullscreen mode

 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> `); }); 
Enter fullscreen mode Exit fullscreen mode

Then, we handle authentication using Passport:

app.post('/login', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login', failureFlash: true }) ); 
Enter fullscreen mode Exit fullscreen mode

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>`); }); 
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
dariomannu profile image
Dario Mannu

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?