const TwoFactorService = require("../services/TwoFactorService"); const logger = require("../utils/logger"); /** * Middleware to require step-up authentication for sensitive actions. * Only applies to users who have 2FA enabled. * * @param {string} action - The sensitive action being protected * @returns {Function} Express middleware function */ const requireStepUpAuth = (action) => { return async (req, res, next) => { try { // If user doesn't have 2FA enabled, skip step-up requirement if (!req.user.twoFactorEnabled) { return next(); } // Check if user has a valid step-up session (within 5 minutes) const isValid = TwoFactorService.validateStepUpSession(req.user); if (!isValid) { logger.info( `Step-up authentication required for user ${req.user.id}, action: ${action}` ); return res.status(403).json({ error: "Multi-factor authentication required", code: "STEP_UP_REQUIRED", action: action, methods: getTwoFactorMethods(req.user), }); } next(); } catch (error) { logger.error("Step-up auth middleware error:", error); return res.status(500).json({ error: "An error occurred during authentication", }); } }; }; /** * Get available 2FA methods for a user * @param {Object} user - User object * @returns {string[]} Array of available methods */ function getTwoFactorMethods(user) { const methods = []; // Primary method is always available if (user.twoFactorMethod === "totp") { methods.push("totp"); } // Email is always available as a backup method methods.push("email"); // Recovery codes are available if any remain if (user.recoveryCodesHash) { const recoveryData = JSON.parse(user.recoveryCodesHash); const remaining = TwoFactorService.getRemainingRecoveryCodesCount(recoveryData); if (remaining > 0) { methods.push("recovery"); } } return methods; } module.exports = { requireStepUpAuth };