Newer
Older
express-blog / src / middleware / authCheck.js
// middleware/authCheck.js
const fetch = require("node-fetch");

const VERIFY_URL = process.env.AUTH_VERIFY;
const CACHE_TTL = parseInt(process.env.AUTH_CACHE_TTL) || 120000; // 2 minutes default

// Simple in-memory cache
const authCache = new Map();

// Helper to generate cache key
function getCacheKey(cookie, authHeader) {
  return `${cookie}:${authHeader}`;
}

// Helper to check if cache entry is valid
function isCacheValid(entry) {
  return entry && Date.now() - entry.timestamp < CACHE_TTL;
}

// Clean expired cache entries periodically
setInterval(() => {
  const now = Date.now();
  for (const [key, entry] of authCache.entries()) {
    if (now - entry.timestamp >= CACHE_TTL) {
      authCache.delete(key);
    }
  }
}, CACHE_TTL); // Clean up when entries would expire

module.exports = async (req, res, next) => {
  const cookie = req.headers["cookie"] || "";
  const authHeader = req.headers["authorization"] || "";
  const cacheKey = getCacheKey(cookie, authHeader);

  // Check cache first
  const cached = authCache.get(cacheKey);
  if (isCacheValid(cached)) {
    req.isAuthenticated = cached.isAuthenticated;
    return next();
  }

  // Default to unauthenticated
  req.isAuthenticated = false;

  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000); // 5 second timeout

    const resVerify = await fetch(VERIFY_URL, {
      headers: {
        cookie,
        authorization: authHeader,
      },
      credentials: "include",
      signal: controller.signal,
    });

    clearTimeout(timeout);

    const isAuthenticated = resVerify.status === 200;

    // Cache the result
    authCache.set(cacheKey, {
      isAuthenticated,
      timestamp: Date.now(),
    });

    req.isAuthenticated = isAuthenticated;
  } catch (err) {
    // Auth server down/timeout - silently fail, don't crash the app
    req.isAuthenticated = false;

    // Optional: Log for debugging, but don't spam logs
    if (req.log) {
      req.log.warn(
        "[AuthCheck] Auth server unavailable, continuing unauthenticated"
      );
    } else {
      console.warn(
        "[AuthCheck] Auth server unavailable, continuing unauthenticated"
      );
    }
  }

  next();
};