How to handle client-sessions in socket.io - node.js

I use client-sessions, not the express sessions. How could I get session data. Session stores on the client, not on a server.
I use client-session module https://github.com/mozilla/node-client-sessions

I found the right answer, to get session from cookie, first you should parse the cookie
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
Than you have to decode the cookie, I used the original function from client-session module
var clientSessions = require('./node_modules/client-sessions/lib/client-sessions')
var opts = {
cookieName: 'yourSessionName'
, secret: 'secret'
}
var decoded = clientSessions.util.decode(opts, handshakeData.cookie['yourSessionName'])
decoded object holds your session data

If you want the session data on the client, you could just use the module's built-in features. If you need it on the server, then you could get the information on client-side and then emit it with socket.io, something like socket.emit('sendSocketData', dataToSend);

Related

Express/Node js api SameSite=None and Secure for cookies ,warning being shown when trying to access the api

I have the following api created using express/node but when i try to access it from the browser "Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use." this warning was shown in console and no data was retrieved ,the api is as follows
let express = require("express");
let app = express();
let bodyparser = require("body-parser")
let jwt = require("jsonwebtoken");
const student = require('./student')
app.use(bodyparser.json)
//used to authenticate the user and create the token
app.get("/auth",(req,res)=>{
console.log("sdsdsds")
var token = jwt.sign({email: user.email}, 'hubDemo', {expiresIn: '1h'});
res.send({token})
})
//fetches the student data and returns
app.get("/student",(req,res)=>{
console.log("tst");
return res.status(200).json({
ok: true,
data: student
});
});
app.listen(3000,()=>{console.log("listening")})
what should i change to make it work?
So in your given scenario, no cookies are being signed our utilized with your express api. However, in the case of your tokens, I would highly recommend looking into http-only cookies rather than localStorage. This prevents any clientside adjustment of the token, while localStorage is more prone to attacks. But depending on your origin-url, just indicating the SameSite property when creating the cookie should solve the warning.

How can I get (Express's) sessionID for a SockJS connection

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.

connect-redis in Nodejs

I have nodejs/express/redis/express-session in use in my nodejs application (express 4.x)
The redis initializing is done by connect-redis/session framework under hood. So far it works. Now I need to use redis to store other data in addition to session, and world like to have a new store other than the session store. Is it just one store possible?
And is it possible to use the redis client initialized by connect-redis/session if only one store is possible? how to get it?
Thanks for the help!
The code now is:
var express = require('express');
var session = require('express-session');
// pass the express to the connect redis module
// allowing it to inherit from session.Store
var RedisStore = require('connect-redis')(session);
....
// Populates req.session
app.use(session({
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
secret: 'keyboard cat',
store: new RedisStore
}));
You'll actually want to initialize a new client for anything else, as the session library is handling it's own client under the hood.
You should most likely import the redis library itself, make your own client, and use that for all future requests / etc.
When I put following code after the code above, I got error
"myRedis Error-> Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED". It seems it is not allowed to init a new Redis instance.
So is there a way to have new client from connect-redis?
var myRedis = require('redis'); // additional redis store
var myRedisCli = myRedis.createClient();
myRedisCli.on('error', function (err) {
console.log('myRedis Error-> ' + err);
});

How to authenticate socket.io connection without underlying useragent to keep the cookies and persist the session

I'm trying to test an app's socket.io which uses passport.socketio to authenticate the socket connection
var socket = require('socket.io-client')('http://localhost:' + app.PORT);
This does not work because there's no accompanying cookie.
Even if I get the cookie from a persisted superagent session
var cookie;
var agent = request.agent(app);
agent.post('/login').send('credentials').end(function(err, res) {
cookie = res.req._headers.cookie;
});
where/how do I use it ?
I found that there are already quite a few requests for socket.io-client to add cookie support
http://github.com/LearnBoost/socket.io-client/issues/450
http://github.com/LearnBoost/socket.io-client/pull/439
http://github.com/LearnBoost/socket.io-client/issues/344
but I don't see them going anywhere.
Is there any other solution to use persistent cookie session with socket while testing?
Cookie data could be passed using querystring
agent.post('/login').send('credentials').end(function(err, res) {
cookie = res.req._headers.cookie.replace(/=/g, '%3D'); //escape '='
});
socket = require('socket.io-client')('http://localhost' + '/?cookie=' + cookie);
It becomes available in the server socket
io.set('authorization', function(handshakeData, callback){
handshakeData._query.cookie;
});
And so it can be used to perform authorization. Since I was using passport.socketio, it plays nicely with a little change to check this query string instead of headers.

Not cookie based session management in node.js

I am looking for a non-cookie based session management in node.js, something like pass a parameter in the URL like &session_id=. It will know that a session has expired when a request comes with an session_id. I've looked at connect library, but it looks that it is cookie based only.
Warning
Passing the session id as a GET parameter is considered bad practice. Why? It is dangerous because people don't usually care about session id and they will probably publish/share links with their session ids inside.
It's also a problem because when a user clicks an external link on your web, and goes to another site, that new site will be able to see the session_id in the referrer link.
So I don't think it is a good idea. Cookies are more secure.
Have a look at: Session Hijacking
For every request you receive, you will get all of the client cookies accordingly.
You can also set client cookies in the response HTTP headers using "Set-Cookie."
Using a GET parameter is unsafe. Any user could accidently share their session ID, but if you want 100% security, I'd share session IDs via cookies, and I would use HTTPS to prevent snoopers from stealing cookies.
You can use localstorage or sessionStorage..
almost same as cookie
not a cookie
better than a cookie!
More info: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
It's very -very- easy to use... in Js for example:
<script>
// check if Storage is avaible
if(typeof(Storage)!=="undefined") {
// Save data to local storage (no exiparion date)
localStorage.setItem("name_always", "bxx");
// Save data to the current session (removes when the tab is closed)
sessionStorage.setItem("name_now", "bxx");
} else {
// No Storage support...
}
// Access to stored data
alert( "For only now, my name is: " + sessionStorage.getItem("name_now"));
alert( "Every day, my name is: " + localStorage.getItem("name_always"));
</script>
Tags: javascript html5 local-storage session-storage
You can use sessions with a store in node.js. For example, you have express application and want to use session like system in your webapp. You can use connect-mongo module for this. This will let you store your session in db. In your app.js
var express = require('express'),
, mongoStore = require('connect-mongo')(express);
var app = express();
app.configure('all', function () {
app.use(express.session({
secret: "terces",
cookie: { maxAge: 24 * 60 * 60 * 1000 },
store: new mongoStore({
url: your_db_url
})
}));
app.use(function(req, res, next) {
res.locals.session = req.session;
next();
});
});
With basic code above, you have session in express that you can use it in your controllers and views directly. In your controller;
app.post('/blog/create/?', function(req, res, next) {
if (!req.session.user) {
next("You need to login in order to create blog!");
}
});
In your view, you can use session.user in order to generate profile menu for example.

Resources