Skip to content

Commit

Permalink
backport fix for cswsh
Browse files Browse the repository at this point in the history
  • Loading branch information
barisusakli committed Jul 19, 2023
1 parent bb997a7 commit 12cba2d
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 20 deletions.
2 changes: 1 addition & 1 deletion install/package.json
Expand Up @@ -54,7 +54,7 @@
"cookie-parser": "1.4.6",
"cron": "1.8.2",
"cropperjs": "1.5.12",
"csurf": "1.11.0",
"csrf-sync": "4.0.1",
"daemon": "1.1.0",
"diff": "5.0.0",
"express": "4.18.0",
Expand Down
3 changes: 3 additions & 0 deletions public/src/sockets.js
Expand Up @@ -12,6 +12,9 @@ socket = window.socket;
reconnectionDelay: config.reconnectionDelay,
transports: config.socketioTransports,
path: config.relative_path + '/socket.io',
query: {
_csrf: config.csrf_token,
},
};

socket = io(config.websocketAddress, ioParams);
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/api.js
Expand Up @@ -9,6 +9,7 @@ const categories = require('../categories');
const plugins = require('../plugins');
const translator = require('../translator');
const languages = require('../languages');
const { generateToken } = require('../middleware/csrf');

const apiController = module.exports;

Expand Down Expand Up @@ -64,7 +65,7 @@ apiController.loadConfig = async function (req) {
'cache-buster': meta.config['cache-buster'] || '',
topicPostSort: meta.config.topicPostSort || 'oldest_to_newest',
categoryTopicSort: meta.config.categoryTopicSort || 'newest_to_oldest',
csrf_token: req.uid >= 0 && req.csrfToken && req.csrfToken(),
csrf_token: req.uid >= 0 ? generateToken(req) : false,
searchEnabled: plugins.hooks.hasListeners('filter:search.query'),
searchDefaultInQuick: meta.config.searchDefaultInQuick || 'titles',
bootswatchSkin: meta.config.bootswatchSkin || '',
Expand Down
28 changes: 28 additions & 0 deletions src/middleware/csrf.js
@@ -0,0 +1,28 @@
'use strict';

const { csrfSync } = require('csrf-sync');

const {
generateToken,
csrfSynchronisedProtection,
isRequestValid,
} = csrfSync({
getTokenFromRequest: (req) => {
if (req.headers['x-csrf-token']) {
return req.headers['x-csrf-token'];
} else if (req.body && req.body.csrf_token) {
return req.body.csrf_token;
} else if (req.body && req.body._csrf) {
return req.body._csrf;
} else if (req.query && req.query._csrf) {
return req.query._csrf;
}
},
size: 64,
});

module.exports = {
generateToken,
csrfSynchronisedProtection,
isRequestValid,
};
5 changes: 3 additions & 2 deletions src/middleware/index.js
Expand Up @@ -2,13 +2,14 @@

const async = require('async');
const path = require('path');
const csrf = require('csurf');
const validator = require('validator');
const nconf = require('nconf');
const toobusy = require('toobusy-js');
const LRU = require('lru-cache');
const util = require('util');

const { csrfSynchronisedProtection } = require('./csrf');

const plugins = require('../plugins');
const meta = require('../meta');
const user = require('../user');
Expand All @@ -34,7 +35,7 @@ middleware.regexes = {
timestampedUpload: /^\d+-.+$/,
};

const csrfMiddleware = csrf();
const csrfMiddleware = csrfSynchronisedProtection;

middleware.applyCSRF = function (req, res, next) {
if (req.uid >= 0) {
Expand Down
3 changes: 2 additions & 1 deletion src/routes/authentication.js
Expand Up @@ -10,6 +10,7 @@ const meta = require('../meta');
const controllers = require('../controllers');
const helpers = require('../controllers/helpers');
const plugins = require('../plugins');
const { generateToken } = require('../middleware/csrf');

let loginStrategies = [];

Expand Down Expand Up @@ -94,7 +95,7 @@ Auth.reloadRoutes = async function (params) {
};

if (strategy.checkState !== false) {
req.session.ssoState = req.csrfToken && req.csrfToken();
req.session.ssoState = generateToken(req, true);
opts.state = req.session.ssoState;
}

Expand Down
38 changes: 25 additions & 13 deletions src/socket.io/index.js
Expand Up @@ -34,13 +34,25 @@ Sockets.init = async function (server) {
}
}

io.use(authorize);

io.on('connection', onConnection);

const opts = {
transports: nconf.get('socket.io:transports') || ['polling', 'websocket'],
cookie: false,
allowRequest: (req, callback) => {
authorize(req, (err) => {
if (err) {
return callback(err);
}
const csrf = require('../middleware/csrf');
const isValid = csrf.isRequestValid({
session: req.session || {},
query: req._query,
headers: req.headers,
});
callback(null, isValid);
});
},
};
/*
* Restrict socket.io listener to cookie domain. If none is set, infer based on url.
Expand All @@ -62,7 +74,11 @@ Sockets.init = async function (server) {
};

function onConnection(socket) {
socket.ip = (socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress || '').split(',')[0];
socket.uid = socket.request.uid;
socket.ip = (
socket.request.headers['x-forwarded-for'] ||
socket.request.connection.remoteAddress || ''
).split(',')[0];
socket.request.ip = socket.ip;
logger.io_one(socket, socket.uid);

Expand Down Expand Up @@ -225,9 +241,7 @@ async function validateSession(socket, errorMsg) {

const cookieParserAsync = util.promisify((req, callback) => cookieParser(req, {}, err => callback(err)));

async function authorize(socket, callback) {
const { request } = socket;

async function authorize(request, callback) {
if (!request) {
return callback(new Error('[[error:not-authorized]]'));
}
Expand All @@ -240,15 +254,13 @@ async function authorize(socket, callback) {
});

const sessionData = await getSessionAsync(sessionId);

request.session = sessionData;
let uid = 0;
if (sessionData && sessionData.passport && sessionData.passport.user) {
request.session = sessionData;
socket.uid = parseInt(sessionData.passport.user, 10);
} else {
socket.uid = 0;
uid = parseInt(sessionData.passport.user, 10);
}
request.uid = socket.uid;
callback();
request.uid = uid;
callback(null, uid);
}

Sockets.in = function (room) {
Expand Down
5 changes: 4 additions & 1 deletion test/helpers/index.js
Expand Up @@ -95,7 +95,7 @@ helpers.logoutUser = function (jar, callback) {
});
};

helpers.connectSocketIO = function (res, callback) {
helpers.connectSocketIO = function (res, csrf_token, callback) {
const io = require('socket.io-client');
let cookies = res.headers['set-cookie'];
cookies = cookies.filter(c => /express.sid=[^;]+;/.test(c));
Expand All @@ -106,6 +106,9 @@ helpers.connectSocketIO = function (res, callback) {
Origin: nconf.get('url'),
Cookie: cookie,
},
query: {
_csrf: csrf_token,
},
});

socket.on('connect', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/socket.io.js
Expand Up @@ -74,7 +74,7 @@ describe('socket.io', () => {
}, (err, res) => {
assert.ifError(err);

helpers.connectSocketIO(res, (err, _io) => {
helpers.connectSocketIO(res, body.csrf_token, (err, _io) => {
io = _io;
assert.ifError(err);

Expand Down

0 comments on commit 12cba2d

Please sign in to comment.