JAVASCRIPT
Implementing CSRF Protection with Express and Tokens
Secure web applications against Cross-Site Request Forgery (CSRF) attacks using `csurf` middleware in Express and managing tokens on the client-side.
// server.js (Node.js with Express)
const express = require('express');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const csurf = require('csurf');
const bodyParser = require('body-parser');
const app = express();
app.use(cookieParser());
app.use(session({
secret: 'a_very_secret_key', // Replace with a strong, random key
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production', // Use secure cookies in production
sameSite: 'Lax', // or 'Strict' depending on requirements
maxAge: 3600000 // 1 hour
}
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(csurf({ cookie: true })); // Enable CSRF protection
// Route to get CSRF token
app.get('/api/csrf-token', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
// Protected route
app.post('/api/submit-data', (req, res) => {
// req.csrfToken() has already been validated by csurf middleware
// Access data from req.body
res.send('Data submitted securely!');
});
// Error handler for CSRF issues
app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
res.status(403).send('Invalid CSRF token.');
} else {
next(err);
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
// client.js (Frontend JavaScript)
async function submitSecureForm(data) {
try {
// Fetch CSRF token
const tokenResponse = await fetch('/api/csrf-token');
const tokenData = await tokenResponse.json();
const csrfToken = tokenData.csrfToken;
// Include CSRF token in the request headers
const response = await fetch('/api/submit-data', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'CSRF-Token': csrfToken // Custom header for CSRF token
},
body: new URLSearchParams({
'someField': data,
'_csrf': csrfToken // Also send in body for csurf default behavior, though header is common too
}).toString()
});
const result = await response.text();
console.log(result);
} catch (error) {
console.error('Error submitting form:', error);
}
}
// Example usage
// submitSecureForm('example_data_to_submit');
How it works: This snippet demonstrates implementing CSRF protection using `csurf` middleware in an Express application. The server generates a unique CSRF token for each user session, making it available via an API endpoint. Frontend JavaScript fetches this token and includes it in subsequent POST requests, either in the request body or a custom header. The `csurf` middleware automatically validates this token against the one stored in the user's session, rejecting requests with missing or invalid tokens, thus preventing CSRF attacks. The `cookie-parser`, `express-session`, and `body-parser` middlewares are prerequisites.