I'm trying to implement sessions in my node.js app which makes heavy use of socket.io. I'm struggling with this currently, and found a rather simple solution which recommends using the socket itself to store the session information. For example:
socket.on('login', function(username) {
if (loginSuccessful() {
socket.sessionID = generateSessionId();
}
});
socket.on('logout', function(username) {
socket.sessionID = null;
});
I am worried that such a simple solution wouldn't be secure, however, I'm not sure if there is any clear vulnerability this solution would have.
Related
I'm new to nodejs and mongodb. in mongodb native driver website they close connection after each request but it seems like to be very slow and problematic in high traffic websites. I'm just curious to know is it necessary to do that or I can declare a global variable and reference that to DB like this:
var mongodbClient = require('mongodb').MongoClient;
var db;
function connect() {
mongodbClient.connect('connection string', function (err, mdb) {
db = mdb;
});
}
connect();
function insert(query, collection, fn) {
db.collection(collection)
.insert(query, function (er, da) {
fn(er, da);
});
}
function find(query, collection, fn) {
db.collection(collection)
.find(query).toArray(function (er, da) {
fn(er, da);
});
}
I don't want to use mongoose and prefer to learn and understand what's going on under the hood.
The examples available in documentation are not actually good for real life use cases. If you are using a server framework you can normally connect to mongo and share reference to the connection throughout application. I use hapi and connect to server via a plugin which allows me to store the handle to open connection. This allows you to clean up on shutdown of server. Their are many modules for managing mongo such as mongoose, waterline or wadofgum-mongodb which I have recently written.
I am choosing a XMPP server, and currently trying NodeXMPP.
I installed complete NodeXMPP (core,server,client,component,dependencies...).
What is striking me is that I have to do all the back-end stuff : making clients speak to each other etc. Other XMPP servers (tigase ejabberd ...) do this stuff from scratch.
My tiny instance :
I create a server and store clients in an array, then search for a client when an other try to speak :
var xmpp = require('../index')
var c2s = new xmpp.C2SServer({
port: 5222,
domain: 'localhost'
})
var clients = new Array();
c2s.on('connect', function(client) {
client.on('authenticate', function(opts, cb) {
console.log('AUTH' + opts.jid + ' -> ' +opts.password)
clients.push(client);
})
client.on('stanza', function(stanza) {
if (stanza.is('message') && (stanza.attrs.type !== 'error')) {
var interlocuteur = getClient(stanza.attrs.to)
if (interlocuteur)
interlocuteur.send(stanza)
}
})
client.on('disconnect', function() {
console.log('DISCONNECT')
})
client.on('online', function() {
console.log('ONLINE')
client.send(new xmpp.Message({ type: 'chat' }).c('body').t('Hello there, little client.'))
})
})
And my question : do I really need to code these basic operations by myself ?
If so, what is the point of Node-XMPP ? Maybe it's to use NodeJS over an other XMPP server like prosody ?
node-xmpp is "just" a library of components that allows you to build your own XMPP client, component or even server.
Being a library, it does not provide a complete solution for particular use case, but a set of building blocks allowing to build one.
If you are in the market of a complete, already made, boxed XMPP server solution, installing Prosody is a good bet. :^)
I am using SockJS on Express server. Is there any way to get the associate HTTP session ID of the client?
I see there is a way to do it for raw web socket and Socket.io, but I am struggling to find how to do it for SockJS.
This is how my server looks like. I want a similar handler to fetch session ID:
var sockjs_echo = sockjs.createServer(sockjs_opts);
sockjs_echo.on('connection', function(conn) {
conn.on('data', function(message) {
conn.write(message);
});
});
This is a "hack", but it works for me:
sockjs_echo.on('connection', function(conn) {
var cookieHeader = conn._session.recv.ws._stream._readableState.pipes._driver._request.headers.cookie
var cookies = {}
cookieHeader.split(';').forEach(function( cookie ) {
var parts = cookie.split('=');
cookies[parts.shift().trim()] = decodeURI(parts.join('='));
});
conn.on('data', function(message) {
conn.write(message);
});
});
'cookies' variable (example):
{
"dev_cookie": "1mimec6rbcolp0ujkcbqq9pdq4uoa5v0p8a284v32tmd4q3k0qi9p4vjteoifdn9b0lsm238fghf974o9jfehfuhvm3ltrgq02ad6k0",
"session_cookie": "s%3AjkKYPKFFT8r60rXUsVYISoOF17o49GUl.pbpu6T1%2BcdrIu5uQPRxZUYOrl5GnC179GaI5pWyR7SA",
"other_cookie": "s%3AzRMiC3fjo4gxTXX1p2XSi_C_EydIa358.KAdP1gwtZBVfcbkmwi%2B3pa0L1pbOCzQ3lHnNEyFvvHc"
}
Thanks so much for asking this question, #darwinbaisa, and for the answer, c-toesca. This came after days of searching.
For XHR streaming, the cookies are at: conn._session.recv.request.headers.cookie.
The only other way I could think of doing this was to make the express session cookie httpOnly: false, thus exposing it to javascript and, of course, the possibility of hacking, then pass it back as a prefix to any message from the SockJS javascript client to the node server.
Or to assign the ID to a javascript variable as I dynamically wrote a web page response, so that javascript would have access to the variable, and again could return it to the server. But again, this would have exposed the ID, and even if the ID was hashed or encrypted, it could still be used in a malicious call to the server from javascript.
Things like this are made a lot easier in the node WS library, but I need a fallback from that for websocket-challenged browsers.
Building a simple app with Posts and Comments.
User hits a Post and adds a comment, everyone who's viewing that same Post will see the new comments added to the post. All done via Socket.io.
This is how I instantiate it:
// app.js
var io = require('socket.io').listen(app.listen(app.get('port')));
var chat = io.of('/p/' + id).on('connection', function(socket) {
socket.on('addComment', function(data) {
var content = data.comment;
var comment = new commentModel({
user: req.user._id,
post_id: id,
content: content
});
comment.save(function(err, doc) {
if (err) {
return next(err);
}
commentModel.findById(doc._id).populate('user').exec(function(err, comment) {
chat.emit('newComment', {
comment: comment
});
});
});
});
});
// client-side JS
self.socket_io = io.connect(window.location.href);
self.socket_io.on('newComment', function(data) {
// do stuff with the new comment
};
The first time you hit the page, the comment is submitted once (one socket connection), however, if I refresh the page and submit a new comment, two are created (one for each connected client).
Any ideas where I'm going wrong?
does
commentModel.findById
nede to be
comment.findByID
?
You could try a few of these:
Manage the socket session on the server: socketio_session[user_id].push(session).
Will give you access to all the sessions connected for a particular user. You probably don't need to store a list of sessions per user, just the latest session, and force disconnect on the existing session, before storing a new session.
--
This list a few things, including changing a config for forcing new connection
https://github.com/LearnBoost/socket.io/issues/474
--
This might also be of use, explains how to extract session id in sockets using express:
http://www.danielbaulig.de/socket-ioexpress/
I think this one might help you out creating new socket connection each time user refresh
https://github.com/wcamarao/session.socket.io/
Ideally, I'd like to find simple, lightweight code that allows all the web clients connected to my site to maintain real-time status of who else is currently online.
I know ejabberd does this, but it also does a lot of other things, and I'd prefer a small code footprint so I can customize and understand its performance characteristics.
I like the non-blocking aspect of node.js, and was wondering if there's an open source project that does all this logic.
I'd also like to see a JavaScript implementation of maintaining this model on the client side.
For real time status, use socket.io. Every time someone connects add them to the connected users list. For accurate stats you will need to keep track of user sessions. See http://www.danielbaulig.de/socket-ioexpress/
var onlineUsers = {};
var online = 0;
io.sockets.on('connection', function (socket) {
onlineUsers[socket.handshake.sessionID] = socket.handshake.session;
online = Object.keys(onlineUsers).length;
socket.broadcast.emit('online', online);
socket.on('disconnect', function () {
delete onlineUsers[socket.handshake.sessionID];
online--;
socket.broadcast.emit('online', online);
});
});
For anyone reading this in the future. I started with the answer written by fent, but I needed some modifications since things have changed in the intervening 6 years since his answer was published.
I used a Map rather than an Object for storing the session information. this means that the sessionID is no longer required.
const onlineUsers = new Map();
io.on('connection', function (socket) {
console.log('connection initiated');
socket.on('userInfo', userInfo => {
console.log('userInfo', userInfo);
onlineUsers.set(socket, userInfo);
io.emit('onlineUsers', Array.from(onlineUsers.values()));
});
socket.on('disconnect', function () {
console.log(onlineUsers.get(socket));
onlineUsers.delete(socket);
io.emit('onlineUsers', Array.from(onlineUsers.values()));
});
});