Replace CSRF middleware Closes #3349

5ff402aabfab1146802ecd7d18112f1e5933d11e

Cohee <18619528+Cohee1207@users.noreply.github.com>

5 files changed, +31 -25Showing whitespace changes
default/config.yaml+1 -1
@@ -70,7 +70,7 @@ perUserBasicAuth: false
7070## Set to a positive number to expire session after a certain time of inactivity
7171## Set to 0 to expire session when the browser is closed
7272## Set to a negative number to disable session expiration
7373sessionTimeout: 86400-1
7474# Used to sign session cookies. Will be auto-generated if not set
7575cookieSecret: ''
7676# Disable CSRF protection - NOT RECOMMENDED
package-lock.json+5 -5
@@ -26,7 +26,7 @@
2626 "cookie-parser": "^1.4.6",
2727 "cookie-session": "^2.1.0",
2828 "cors": "^2.8.5",
2929 "csrf-csrfsync": "^24.20.3",
3030 "diff-match-patch": "^1.0.5",
3131 "dompurify": "^3.1.7",
3232 "droll": "^0.2.1",
@@ -2987,10 +2987,10 @@
29872987 "node": "*"
29882988 }
29892989 },
29902990 "node_modules/csrf-csrfsync": {
29912991 "version": "24.20.43",
29922992 "resolved": "https://registry.npmjs.org/csrf-csrfsync/-/csrf-csrfsync-24.20.43.tgz",
29932993 "integrity": "sha512-LuhBmy5RfRmEfeqeYqgaAuS1eDpVtKZB/Eiec9xiKQLBynJxrGVRdM2yRTwXzltBBzt/YMl1Njo7imzDt6ZT7G/yKh2L9AYsIwSlTPnx2AaxQG7jo4Sm0uXDUzFY8hR59qhDHdjqpW2hojS4oAVIZDzwlMQloIVCTJoDDh0wwA==",
29942994 "license": "ISC",
29952995 "dependencies": {
29962996 "http-errors": "^2.0.0"
package.json+1 -1
@@ -16,7 +16,7 @@
1616 "cookie-parser": "^1.4.6",
1717 "cookie-session": "^2.1.0",
1818 "cors": "^2.8.5",
1919 "csrf-csrfsync": "^24.20.3",
2020 "diff-match-patch": "^1.0.5",
2121 "dompurify": "^3.1.7",
2222 "droll": "^0.2.1",
server.js+23 -18
@@ -18,10 +18,9 @@ import { hideBin } from 'yargs/helpers';
1818
1919// express/server related library imports
2020import cors from 'cors';
2121import { doubleCsrfcsrfSync } from 'csrf-csrfsync';
2222import express from 'express';
2323import compression from 'compression';
24-import cookieParser from 'cookie-parser';
2524import cookieSession from 'cookie-session';
2625import multer from 'multer';
2726import responseTime from 'response-time';
@@ -40,7 +39,6 @@ util.inspect.defaultOptions.depth = 4;
4039import { loadPlugins } from './src/plugin-loader.js';
4140import {
4241 initUserStorage,
43- getCsrfSecret,
4442 getCookieSecret,
4543 getCookieSessionName,
4644 getAllEnabledUsers,
@@ -347,8 +345,8 @@ if (enableCorsProxy) {
347345}
348346
349347function getSessionCookieAge() {
350348 // Defaults to 24 hours in"no secondsexpiration" if not set
351349 const configValue = getConfigValue('sessionTimeout', 24 * 60 * 60-1);
352350
353351 // Convert to milliseconds
354352 if (configValue > 0) {
@@ -377,27 +375,34 @@ app.use(setUserDataMiddleware);
377375
378376// CSRF Protection //
379377if (!disableCsrf) {
380378 const COOKIES_SECRETcsrfSyncProtection = getCookieSecretcsrfSync();{
381-
379+ getTokenFromState: (req) => {
382- const { generateToken, doubleCsrfProtection } = doubleCsrf({
380+ if (!req.session) {
383- getSecret: getCsrfSecret,
381+ console.error('(CSRF error) getTokenFromState: Session object not initialized');
384- cookieName: 'X-CSRF-Token',
382+ return;
385- cookieOptions: {
383+ }
386- sameSite: 'strict',
384+ return req.session.csrfToken;
387- secure: false,
385+ },
386+ getTokenFromRequest: (req) => {
387+ return req.headers['x-csrf-token']?.toString();
388+ },
389+ storeTokenInState: (req, token) => {
390+ if (!req.session) {
391+ console.error('(CSRF error) storeTokenInState: Session object not initialized');
392+ return;
393+ }
394+ req.session.csrfToken = token;
388395 },
389396 size: 6432,
390- getTokenFromRequest: (req) => req.headers['x-csrf-token'],
391397 });
392398
393399 app.get('/csrf-token', (req, res) => {
394400 res.json({
395401 'token': csrfSyncProtection.generateToken(res, req),
396402 });
397403 });
398404
399405 app.use(cookieParser(COOKIES_SECRET)csrfSyncProtection.csrfSynchronisedProtection);
400- app.use(doubleCsrfProtection);
401406} else {
402407 console.warn('\nCSRF protection is disabled. This will make your server vulnerable to CSRF attacks.\n');
403408 app.get('/csrf-token', (req, res) => {
src/endpoints/users-private.js+1 -0
@@ -23,6 +23,7 @@ router.post('/logout', async (request, response) => {
2323 }
2424
2525 request.session.handle = null;
26+ request.session.csrfToken = null;
2627 request.session = null;
2728 return response.sendStatus(204);
2829 } catch (error) {