Back to Express JS Course

Express JS Course

Passport JS is a popular authentication middleware for Node JS applications, particularly those using Express JS. It provides a straightforward way to handle user authentication, allowing you to authenticate requests via various strategies such as username/password, social login (OAuth), or other third-party authentication services.

Lets refactor our code to include passport.

First, install Passport npm install passport passport-local

usersRouter.mjs

import express from 'express'; import { checkSchema, validationResult } from 'express-validator'; import { createUserValidationSchema } from '../utils/validationSchemas.mjs'; import session from 'express-session'; import passport from 'passport'; // Import Passport import LocalStrategy from 'passport-local'; // Import LocalStrategy const router = express.Router(); router.use(session({ secret: 'praveenoruganti', resave: false, saveUninitialized: false, cookie: { maxAge: 900000, // 15 minutes httpOnly: true, } })); // Initialize Passport and session middleware router.use(passport.initialize()); router.use(passport.session()); const mockUsers = [ { id: 1, name: 'Praveen',username: 'praveen', password: 'test@123', designation: 'Technical Architect', city: 'Hyderabad' }, { id: 2, name: 'Prasad',username: 'prasad', password: 'test@1234', designation: 'Technical Lead', city: 'Bangalore' }, { id: 3, name: 'Anusha',username: 'anusha', password: 'test@12345', designation: 'Lead Developer', city: 'Chennai' }, { id: 4, name: 'Ravi',username: 'ravi', password: 'sample@123', designation: 'Developer', city: 'Hyderabad' }, { id: 5, name: 'Kiran',username: 'kiran', password: 'sample@1234', designation: 'Technical Lead', city: 'Hyderabad' }, ]; // Passport Local Strategy passport.use(new LocalStrategy( function(username, password, done) { const user = mockUsers.find(u => u.username === username && u.password === password); if (!user) { return done(null, false, { message: 'Incorrect username or password' }); } return done(null, user); } )); // Serialize and deserialize user passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { const user = mockUsers.find(u => u.id === id); done(null, user); }); // Middleware for authentication const authenticate = (req, res, next) => { if (req.isAuthenticated()) { return next(); } res.status(401).send('Unauthorized'); }; // Login route using Passport's authenticate middleware router.post('/login', passport.authenticate('local'), (req, res) => { // If authentication succeeds, this function will be called req.session.authenticated = true; res.send('Login successful'); }); // Route to logout router.get('/logout', (req, res) => { req.logout(); // Terminate the login session req.session.destroy(err => { if (err) { console.error('Error destroying session:', err); return res.status(500).send('Internal Server Error'); } res.send('Logged out successfully'); }); }); // Route to get all users router.get('/', authenticate, (req, res) => { const isAuthenticated = req.session.authenticated; if (!isAuthenticated) { return res.status(401).send('Unauthorized'); } let filteredUsers = mockUsers; const { name, designation, city } = req.query; if (name) { filteredUsers = filteredUsers.filter(user => user.name.toLowerCase().includes(name.toLowerCase())); } if (designation) { filteredUsers = filteredUsers.filter(user => user.designation.toLowerCase().includes(designation.toLowerCase())); } if (city) { filteredUsers = filteredUsers.filter(user => user.city.toLowerCase().includes(city.toLowerCase())); } res.send({ users: filteredUsers }); }); // Route to get a single user by ID router.get('/:id', (req, res) => { const parsedId = parseInt(req.params.id); if (isNaN(parsedId)) res.status(400).send({ msg: "Bad Request. Invalid ID" }); const findUser = mockUsers.find((user) => user.id === parsedId); if (!findUser) res.status(404).send({ msg: "ID Not Found" }); res.send(findUser); }); // Route to add a new user router.post('/', checkSchema(createUserValidationSchema), (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } const newUser = req.body; // Validate the incoming data if (!newUser.name || !newUser.designation || !newUser.city) { return res.status(400).send({ msg: 'Bad Request. Missing required fields' }); } // Assign a new ID to the new user newUser.id = mockUsers.length ? mockUsers[mockUsers.length - 1].id + 1 : 1; // Add the new user to the mockUsers array mockUsers.push(newUser); // Respond with the newly created user res.status(201).send({ user: newUser }); }); // Route to update an existing user router.put('/:id', (req, res) => { const parsedId = parseInt(req.params.id, 10); if (isNaN(parsedId)) { return res.status(400).send({ msg: 'Bad Request. Invalid ID' }); } const findUser = mockUsers.find((user) => user.id === parsedId); if (!findUser) { return res.status(404).send({ msg: 'ID Not Found' }); } const { name, designation, city } = req.body; if (!name || !designation || !city) { return res.status(400).send({ msg: 'Bad Request. Missing required fields' }); } // Update user data findUser.name = name; findUser.designation = designation; findUser.city = city; res.send({ user: findUser }); }); // PATCH endpoint to update user by ID router.patch('/:id', (req, res) => { const id = parseInt(req.params.id); const updatedUser = req.body; // Find the user by ID const userToUpdate = mockUsers.find(user => user.id === id); // If the user is found, update its properties if (userToUpdate) { userToUpdate.name = updatedUser.name; userToUpdate.designation = updatedUser.designation; userToUpdate.city = updatedUser.city; res.status(200).json({ message: 'User updated successfully', user: userToUpdate }); } else { res.status(404).json({ message: 'User not found' }); } }); // Route to delete a user router.delete('/:id', (req, res) => { const userId = parseInt(req.params.id); const userIndex = mockUsers.findIndex(user => user.id === userId); if (userIndex !== -1) { mockUsers.splice(userIndex, 1); res.status(204).send(); // No Content } else { res.status(404).send('User not found'); } }); export default router;

Lets invoke POST /login method with username and password.

screenshot of the app

Lets invoke get all users endpoint as session is set.

screenshot of the app

Lets invoke POST /logout so that it will clear the session.

screenshot of the app