const express = require('express'); const cookieParser = require('cookie-parser'); const session = require('express-session'); const csrf = require('csurf'); // A common CSRF protection middleware const app = express(); // Use cookie-parser middleware for parsing cookies app.use(cookieParser()); // Use express-session middleware for session management // IMPORTANT: Configure strong secret, secure: true, httpOnly: true for production app.use(session({ secret: 'a_very_secret_string_that_should_be_long_and_random', resave: false, saveUninitialized: true, cookie: { secure: true, httpOnly: true, sameSite: 'Lax' } // 'secure' for HTTPS only })); // Set up CSRF protection // cookie: true tells csurf to use a cookie to store the token const csrfProtection = csrf({ cookie: true }); // Middleware to expose CSRF token to templates app.use((req, res, next) => { if (req.csrfToken) { res.locals.csrfToken = req.csrfToken(); } next(); }); // Apply CSRF protection to routes that modify state (POST, PUT, DELETE) app.get('/', csrfProtection, (req, res) => { // In a real application, you'd render an HTML form here // and inject res.locals.csrfToken into a hidden input field. res.send(`
CSRF Token: ${res.locals.csrfToken}
`); }); app.post('/process', csrfProtection, (req, res) => { // Access req.body for form data if using body-parser res.send('Form data processed successfully! CSRF token validated.'); }); // Example without CSRF protection (DO NOT DO THIS FOR STATE-CHANGING ROUTES) app.post('/insecure-process', (req, res) => { res.send('Insecure form data processed (NO CSRF protection!).'); }); // Error handling for CSRF issues app.use((err, req, res, next) => { if (err.code === 'EBADCSRFTOKEN') { res.status(403).send('Invalid CSRF token.'); } else { next(err); } }); const PORT = 3000; app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); });