mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
poc: use csrf_token in ws handshake (#11573)
This commit is contained in:
committed by
GitHub
parent
180326a420
commit
63b859f053
@@ -15,6 +15,9 @@ app = window.app || {};
|
|||||||
reconnectionDelay: config.reconnectionDelay,
|
reconnectionDelay: config.reconnectionDelay,
|
||||||
transports: config.socketioTransports,
|
transports: config.socketioTransports,
|
||||||
path: config.relative_path + '/socket.io',
|
path: config.relative_path + '/socket.io',
|
||||||
|
query: {
|
||||||
|
_csrf: config.csrf_token,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.socket = io(config.websocketAddress, ioParams);
|
window.socket = io(config.websocketAddress, ioParams);
|
||||||
|
|||||||
@@ -5,12 +5,15 @@ const { csrfSync } = require('csrf-sync');
|
|||||||
const {
|
const {
|
||||||
generateToken,
|
generateToken,
|
||||||
csrfSynchronisedProtection,
|
csrfSynchronisedProtection,
|
||||||
|
isRequestValid,
|
||||||
} = csrfSync({
|
} = csrfSync({
|
||||||
getTokenFromRequest: (req) => {
|
getTokenFromRequest: (req) => {
|
||||||
if (req.headers['x-csrf-token']) {
|
if (req.headers['x-csrf-token']) {
|
||||||
return req.headers['x-csrf-token'];
|
return req.headers['x-csrf-token'];
|
||||||
} else if (req.body.csrf_token) {
|
} else if (req.body && req.body.csrf_token) {
|
||||||
return req.body.csrf_token;
|
return req.body.csrf_token;
|
||||||
|
} else if (req.query) {
|
||||||
|
return req.query._csrf;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
size: 64,
|
size: 64,
|
||||||
@@ -19,4 +22,5 @@ const {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
generateToken,
|
generateToken,
|
||||||
csrfSynchronisedProtection,
|
csrfSynchronisedProtection,
|
||||||
|
isRequestValid,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,13 +34,25 @@ Sockets.init = async function (server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
io.use(authorize);
|
|
||||||
|
|
||||||
io.on('connection', onConnection);
|
io.on('connection', onConnection);
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
transports: nconf.get('socket.io:transports') || ['polling', 'websocket'],
|
transports: nconf.get('socket.io:transports') || ['polling', 'websocket'],
|
||||||
cookie: false,
|
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.
|
* Restrict socket.io listener to cookie domain. If none is set, infer based on url.
|
||||||
@@ -62,7 +74,11 @@ Sockets.init = async function (server) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onConnection(socket) {
|
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;
|
socket.request.ip = socket.ip;
|
||||||
logger.io_one(socket, socket.uid);
|
logger.io_one(socket, socket.uid);
|
||||||
|
|
||||||
@@ -231,9 +247,7 @@ async function validateSession(socket, errorMsg) {
|
|||||||
|
|
||||||
const cookieParserAsync = util.promisify((req, callback) => cookieParser(req, {}, err => callback(err)));
|
const cookieParserAsync = util.promisify((req, callback) => cookieParser(req, {}, err => callback(err)));
|
||||||
|
|
||||||
async function authorize(socket, callback) {
|
async function authorize(request, callback) {
|
||||||
const { request } = socket;
|
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return callback(new Error('[[error:not-authorized]]'));
|
return callback(new Error('[[error:not-authorized]]'));
|
||||||
}
|
}
|
||||||
@@ -246,15 +260,13 @@ async function authorize(socket, callback) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const sessionData = await getSessionAsync(sessionId);
|
const sessionData = await getSessionAsync(sessionId);
|
||||||
|
request.session = sessionData;
|
||||||
|
let uid = 0;
|
||||||
if (sessionData && sessionData.passport && sessionData.passport.user) {
|
if (sessionData && sessionData.passport && sessionData.passport.user) {
|
||||||
request.session = sessionData;
|
uid = parseInt(sessionData.passport.user, 10);
|
||||||
socket.uid = parseInt(sessionData.passport.user, 10);
|
|
||||||
} else {
|
|
||||||
socket.uid = 0;
|
|
||||||
}
|
}
|
||||||
request.uid = socket.uid;
|
request.uid = uid;
|
||||||
callback();
|
callback(null, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sockets.in = function (room) {
|
Sockets.in = function (room) {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ helpers.logoutUser = function (jar, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers.connectSocketIO = function (res, callback) {
|
helpers.connectSocketIO = function (res, csrf_token, callback) {
|
||||||
const io = require('socket.io-client');
|
const io = require('socket.io-client');
|
||||||
let cookies = res.headers['set-cookie'];
|
let cookies = res.headers['set-cookie'];
|
||||||
cookies = cookies.filter(c => /express.sid=[^;]+;/.test(c));
|
cookies = cookies.filter(c => /express.sid=[^;]+;/.test(c));
|
||||||
@@ -107,6 +107,9 @@ helpers.connectSocketIO = function (res, callback) {
|
|||||||
Origin: nconf.get('url'),
|
Origin: nconf.get('url'),
|
||||||
Cookie: cookie,
|
Cookie: cookie,
|
||||||
},
|
},
|
||||||
|
query: {
|
||||||
|
_csrf: csrf_token,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ describe('socket.io', () => {
|
|||||||
}, (err, res) => {
|
}, (err, res) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
||||||
helpers.connectSocketIO(res, (err, _io) => {
|
helpers.connectSocketIO(res, body.csrf_token, (err, _io) => {
|
||||||
io = _io;
|
io = _io;
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user