/*********************************************************************************************************************************************************************** * File Name: csrf.middleware.js * Type of Program: Middleware * Description: CSRF protection using the `csurf` package (Double Submit Cookie pattern). * - csrfProtection → the csurf middleware instance (attach to state-changing routes) * - getCsrfToken → GET /csrf-token handler — sends the token to the client * - csrfErrorHandler → catches EBADCSRFTOKEN and returns a 403 * * NOTE: Because we use stateless JWT (no server sessions), CSRF is only * relevant for cookie-based flows (e.g., CSRF token embedded in form headers). * For REST / SPA clients, the standard practice is to omit CSRF and rely on * the Authorization Bearer header (which is already CSRF-safe by design). * This file keeps CSRF available for SSR / hybrid flows. * * Author: rgrgogu * Date Created: Oct. 6, 2025 *********************************************************************************************************************************************************************** * HOW TO USE: * // 1. Mount the token endpoint (public): * app.get('/api/csrf-token', getCsrfToken); * * // 2. Apply to state-mutating cookie-based routes: * router.post('/login', csrfProtection, loginHandler); * * // 3. Register the error handler AFTER all routes: * app.use(csrfErrorHandler); ***********************************************************************************************************************************************************************/ const csurf = require('csurf'); const R = require('../utils/response.util'); /** csurf instance — stores token in a signed cookie */ const csrfProtection = csurf({ cookie: { httpOnly: true, sameSite: 'strict' } }); /** * GET /api/csrf-token * Returns the CSRF token the client must echo back on state-changing requests * via the `X-CSRF-Token` header or `_csrf` body field. */ const getCsrfToken = (req, res) => { res.json({ csrfToken: req.csrfToken() }); }; /** * Error handler for invalid / missing CSRF tokens. * Must be registered as Express error-handling middleware (4 args). */ const csrfErrorHandler = (err, req, res, next) => { if (err.code === 'EBADCSRFTOKEN') return R.error(res, 'Invalid or missing CSRF token.', 403); next(err); }; module.exports = { csrfProtection, getCsrfToken, csrfErrorHandler };