Login Authentication with Express and Passport

25 February 2025 592 views

Instead of having to use json web tokens for authentication there had to be a simpler way to handle authentication for small applications . Token authentication is better for large applications with multiple databases. For small applications with one database, session-based authentication is a simpler approach to implement and test.


Step 1: Start The Express Server

const express = require('express');
const session = require('express-session');
const passport = require('passport');
const MongoStore = require('connect-mongo');
const mongoose = require('mongoose');
require('dotenv').config();

const app = express();
app.use(express.json()); // Parse incoming JSON


Step 2: Configure Sessions with express-session and MongoDB

app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,             
    saveUninitialized: false, 
    store: MongoStore.create({ 
        mongoUrl: process.env.MONGO_URI,
        collectionName: 'sessions'
    }),
    cookie: { // Set cookie
        maxAge: 1000 * 60 * 60 * 24,  // 24 hours
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax'
    }
}));


Step 3: Initialize Passport

app.use(passport.initialize());
app.use(passport.session()); // Enables persistent login sessions


Step 4: Configure Passport Serialization

Passport determines what user data to store in the session using serializeUser(), and how to retrieve the user with deserializeUser().


const User = require('./models/User'); // Adjust path to your user model


passport.serializeUser((user, done) => {
    done(null, user.id); // Store only the user ID in the session
});


passport.deserializeUser(async (id, done) => {
    try {
        const user = await User.findById(id);
        done(null, user); // Adds user object to req.user
    } catch (err) {
        done(err, null);
    }
});



If you want to store additional info (like auth type, timestamps, etc.), you can serialize an object instead of just user.id.

Storing data to session object:


Step 5: Create a Session After Login

Here’s a sample route to manually create a session — for example, after a user logs in via a custom frontend:

const express = require('express');
const router = express.Router();
const User = require('../models/User');


router.post('/create-session', async (req, res) => {
    const { isLoggedIn, userId } = req.body;


    try {
        if (!isLoggedIn) {
            return res.status(400).json({ success: false, error: 'User is not logged in.' });
        }


        const user = await User.findById(userId);
        if (!user) {
            return res.status(404).json({ success: false, error: 'User not found.' });
        }


        req.login(user, (err) => {
            if (err) {
                return res.status(500).json({ success: false, error: 'Failed to create session.' });
            }
            return res.json({ success: true });
        });


    } catch (error) {
        console.error(error);
        res.status(500).json({ success: false, error: 'A server error has occurred.' });
    }
});


module.exports = router;





***Note***: In most real-world applications, you'd authenticate the user with credentials first (e.g., with Passport's local strategy), then call req.login() upon successful authentication.




Step 6: Checking if a User is Authenticated

Use Passport's req.isAuthenticated() method to protect routes:


app.get('/', (req, res) => {
    if (req.isAuthenticated()) {
        res.sendFile(path.join(__dirname, 'public/views/index.html'));
    } else {
        res.sendFile(path.join(__dirname, 'public/views/auth/index.html'));
    }
});



You can also write middleware:

function ensureAuth(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    }
    res.redirect('/login');
}


When to Use Session-Based Auth

Use session-based authentication when:

  • You control both frontend and backend (monolithic apps).
  • Your backend is centralized and doesn't need to be stateless.
  • You want to avoid managing token expiration, refresh logic, and extra database lookups for token validation.



Comments

S
surpol
suryapolina@gmail.com

thanks for your input @kitsVA

31 October 2024 at 00:17
K
kitsVA
krishnapolina@gmail.com

infoseek, aol, and altavista were big and leaders of those era

21 October 2024 at 18:54