/**
 * CSRF protection using the double-submit cookie pattern.
 *
 * On login the server issues a random `csrf_token` cookie (httpOnly:false
 * so JS can read it). The SPA must send the same value in the
 * `X-CSRF-Token` request header for every state-changing request (POST,
 * PUT, PATCH, DELETE).
 *
 * Because the `sameSite: strict` session cookie already provides strong
 * protection in modern browsers, this acts as defence-in-depth for
 * older browsers and any edge cases.
 *
 * Safe methods (GET, HEAD, OPTIONS) are exempted.
 */

const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);

function verifyCsrf(req, res, next) {
  if (SAFE_METHODS.has(req.method)) return next();

  const cookieToken = req.cookies.csrf_token;
  const headerToken = req.headers['x-csrf-token'];

  if (!cookieToken || !headerToken) {
    return res.status(403).json({ error: 'CSRF token missing' });
  }

  // Constant-time comparison to prevent timing attacks
  if (cookieToken.length !== headerToken.length) {
    return res.status(403).json({ error: 'CSRF token invalid' });
  }

  const a = Buffer.from(cookieToken);
  const b = Buffer.from(headerToken);
  if (!require('crypto').timingSafeEqual(a, b)) {
    return res.status(403).json({ error: 'CSRF token invalid' });
  }

  next();
}

module.exports = verifyCsrf;
