Source

middleware/auth.js

/**
 * Authentication Middleware
 * 
 * This module provides JWT-based authentication middleware for the Social Media Dashboard API.
 * It handles token verification, user authentication, and token generation for secure API access.
 * 
 * @author Ignas Panavas
 * @version 1.0.0
 */

const jwt = require('jsonwebtoken');
const User = require('../models/User');

/**
 * Authenticate JWT Token Middleware
 * 
 * Verifies JWT tokens from the Authorization header and attaches the authenticated user to the request object.
 * This middleware should be used on protected routes that require user authentication.
 * 
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object  
 * @param {Function} next - Express next middleware function
 * 
 * @returns {void} Calls next() if authentication succeeds, sends error response if it fails
 * 
 * @example
 * // Protect a route
 * router.get('/protected', authenticateToken, (req, res) => {
 *   // req.user is now available with the authenticated user
 *   res.json({ user: req.user });
 * });
 */
const authenticateToken = async (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

  if (!token) {
    return res.status(401).json({ message: 'Access token required' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    const user = await User.findById(decoded.userId);
    
    if (!user) {
      return res.status(401).json({ message: 'Invalid token - user not found' });
    }
    
    req.user = user;
    next();
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      return res.status(401).json({ message: 'Token expired' });
    }
    return res.status(403).json({ message: 'Invalid token' });
  }
};

/**
 * Generate JWT Access Token
 * 
 * Creates a new JWT access token for the specified user. Access tokens are used for API authentication
 * and have a shorter expiration time for security.
 * 
 * @param {string} userId - The MongoDB ObjectId of the user
 * @returns {string} JWT access token
 * 
 * @example
 * const token = generateToken('507f1f77bcf86cd799439011');
 * // Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
 */
const generateToken = (userId) => {
  return jwt.sign(
    { userId },
    process.env.JWT_SECRET,
    { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
  );
};

/**
 * Generate JWT Refresh Token
 * 
 * Creates a new JWT refresh token for the specified user. Refresh tokens are used to obtain new
 * access tokens without requiring the user to log in again. They have a longer expiration time.
 * 
 * @param {string} userId - The MongoDB ObjectId of the user
 * @returns {string} JWT refresh token
 * 
 * @example
 * const refreshToken = generateRefreshToken('507f1f77bcf86cd799439011');
 * // Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
 */
const generateRefreshToken = (userId) => {
  return jwt.sign(
    { userId, type: 'refresh' },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '30d' }
  );
};

module.exports = {
  authenticateToken,
  generateToken,
  generateRefreshToken
};