@gov-cy/govcy-express-services
Version:
An Express-based system that dynamically renders services using @gov-cy/govcy-frontend-renderer and posts data to a submission API.
51 lines (44 loc) • 1.59 kB
JavaScript
import { handleMiddlewareError } from "../utils/govcyUtils.mjs";
import { errorResponse } from '../utils/govcyApiResponse.mjs';
import { isApiRequest } from '../utils/govcyApiDetection.mjs';
/**
* Middleware to handle CSRF token generation and validation.
*
* @param {object} req The request object
* @param {object} res The response object
* @param {object} next The next middleware function
*/
export function govcyCsrfMiddleware(req, res, next) {
// Generate token on first request per session
if (!req.session.csrfToken) {
req.session.csrfToken = generateRandonToken();
}
req.csrfToken = () => req.session.csrfToken;
if (
req.method === 'POST' &&
req.headers['content-type']?.includes('multipart/form-data') &&
isApiRequest(req)) {
const tokenFromHeader = req.get('X-CSRF-Token');
// UNCOMMENT
if (!tokenFromHeader || tokenFromHeader !== req.session.csrfToken) {
return res.status(400).json(errorResponse(403, 'Invalid CSRF token'));
}
return next();
}
// Check token on POST requests
if (req.method === 'POST') {
const tokenFromBody = req.body._csrf;
if (!tokenFromBody || tokenFromBody !== req.session.csrfToken) {
return handleMiddlewareError("🚨 Invalid CSRF token", 403, next); // Pass error to govcyHttpErrorHandler
}
}
next();
}
/**
* Generate a random token string.
*
* @returns {string} A random token string
*/
export function generateRandonToken() {
return [...Array(32)].map(() => Math.random().toString(36)[2]).join('');
}