Node.js Handle session with database - node.js

Basically I have a Node.js web application which uses the express-session module to handle sessions.
It works perfectly but with 1 expectation which ruins this option for me. If the Server crashes or I deploy a new release, the sessions get wiped out complety and thats unacceptable for me. Also its bad that I cant share the session between my main and my backup server.
So my goal is to handle the session via a external cloud database, just think of it as a "casual mysql database".
But here is the point were I just get confused on how to do that. I can assign unique ids to the sessions and depending on those load the resources from the database, but how can I re-recognize the users if these sessions get wiped away?
I am lacking alot of knowledge about sessions, but since this is quite a critical topic for me I post a question here.

You can use any of those stores (or write your own) :
https://www.npmjs.com/package/express-session#compatible-session-stores
I'm using the connect mongo to store sessions in my mongo DB, code looks like this (app.js) :
import session from 'express-session';
const MongoStore = require('connect-mongo')(session);
...
...
api.use(session({
secret: global.config.secrets.session,
saveUninitialized: false, // don't create session until something stored
resave: false, //don't save session if unmodified
store: new MongoStore({
mongooseConnection: mongoose.connection,
touchAfter: 24 * 3600 // time period in seconds
})
}));

Related

How to destroy the session (store)?

For authentification I'm trying to understand, how sessions work. With help of documentation of express session and Sessions in Node JS I got it work.
Now I'm figuring out, what to do, that users can log out. In the documentation of express session is to read "The default server-side session storage, MemoryStore, is purposely not designed for a production environment." They recommand a compatible session store.
I have choosen connect-redis. They call it an "in-memory data structure store". Now I'm wondering, what is the difference between redis and the database, that I would like to use (back4app).
If I implement connect-redis
const RedisStore = require('connect-redis')(session);
const redis = require("redis").createClient();
let sess = {
store: new RedisStore({ host: 'localhost', 6379, client: redis }),
secret: cryptoString,
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 1 * 60 * 1000,
},
}
server.use(session(sess));
the user object from back4app stills undefined. (Without redis the user object exists.)
As mentioned I have tryed Parse.User.logOut(). It doesn't work. The console says Parse.User is null.
Please, explain
what is the difference between back4app and redis? Do I need both?
how do I enable log out?
For all with the same problem. This is my other question in this context. It will help you to see the whole picture.

Keep express sessions on NodeJS restart

I use express-session
app.use(require('express-session')({ resave: false, saveUninitialized: false }));
And I would like to know if it's possible to keep sessions after NodeJS server restart ?
Thank you very much
(User is disconnected after every server reload)
Sessions are stored in memory so if your NodeJS server restarts, all the session data is lost.
You will have to use a database to store the session data.
The documentation has a list of modules available to connect with the database.
https://www.npmjs.com/package/express-session#compatible-session-stores

Authentication with Node/Express/Socket.IO

I have a node/socket.io/express server that's connected to a HTML file (like so). So visiting the web address connects you to the server. I am trying to set up a system where by, said server is being run on multiple computers at a time and by way of some sort of username and password authentication, visiting the webpage with specific credentials connects you to one of the computers with those same credentials running the server.
Ive seen mention of "Redis" from previous similar questions but they are pretty old and im wondering if there is a newer or better way of achieving this.
You won't find a lot of up-to-date documentation since Express 4 is kind of new, so let me try to remedy that here :
Authentication in Express 4.x and Socket.IO 1.x
Let's start with a confusion I think you're making:
What is Redis?
Redis is a data structure engine. It allows you to store key/values pairs, nothing more (In this context). The only thing it can do for you when building your authentication system is storing the data, user info, session ids, etc. In your case, you can share a store between multiple machines, the same way you'd share a database, or a text file.
Redis
Authenticate user to node/express server
One of the ways you can do that is by using passport. Passport is a middleware dedicated to authentication on Node.js. It is made for use with Express and relatively easy to setup. There is an excellent tutorial series on how to setup passport with your express application, so I won't detail this part, please take the time to go through the series, it's invaluable knowledge.
Here's the link to the first part, which is the one I'll focus on for the next step.
Add socket.io to the mix
Socket.io doesn't have access to the session cookies that you create in part 1. To remedy that, we will use the passport-socketio module.
Passport-socketio requires a local session store, as opposed to a memory store. This means we need some way to store the session data somewhere, does that ring a bell?
Exactly, Redis.
You can try other stores, like mongoDB or MySQL, but Redis is the fastest.
In this example, I'll assume that your express app and passport are already operational and will focus on adding socket.io to the app.
Setup :
var session = require('express-session'); //You should already have this line in your app
var passportSocketIo = require("passport.socketio");
var io = require("socket.io")(server);
var RedisStore = require('connect-redis')(session);
var sessionStore = new RedisStore({ // Create a session Store
host: 'localhost',
port: 6379,
});
app.use(session({
store: sessionStore, //tell express to store session info in the Redis store
secret: 'mysecret'
}));
io.use(passportSocketIo.authorize({ //configure socket.io
cookieParser: cookieParser,
secret: 'mysecret', // make sure it's the same than the one you gave to express
store: sessionStore,
success: onAuthorizeSuccess, // *optional* callback on success
fail: onAuthorizeFail, // *optional* callback on fail/error
}));
Connect-redis is a session store package that uses redis (in case the name isn't obvious).
Final step :
function onAuthorizeSuccess(data, accept){
console.log('successful connection to socket.io');
accept(); //Let the user through
}
function onAuthorizeFail(data, message, error, accept){
if(error) accept(new Error(message));
console.log('failed connection to socket.io:', message);
accept(null, false);
}
io.sockets.on('connection', function(socket) {
console.log(socket.request.user);
});
The user object found in socket.request will contain all the user info from the logged in user, you can pass it around, or do whatever you need with it from this point.
Note : This setup will be slightly different for Socket.IO < 1.x

Managing persistence sessions in NodeJS

i'm trying to set up a very basic session manager. So, first i came with this code:
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
// define session store
app.use(session({
secret: 'meh',
saveUninitialized: true,
resave: true,
store: new MongoStore({
db : 'express'
})
}));
My current setup is nodejs/express4 with all modules installed locally.
now, how can i share this app without having problems with connect-mongo? because, if i run it on other machine, i get this error:
"error connection to database:failed to connect to [127.0.0.1:27017]..."
Do you know what may be wrong ?
The most obvious mistake here would be: there is no running MongoDB instance on the other machine.
If you want to connect to a remote server you have to specify the location and (hopefully) credentials. Have a look at: https://github.com/kcbanner/connect-mongo#options

session storage on mongo DB is creating one line on DB for each http request and not one per login/sign up

Using connect-mongo to handle session storage, I am getting a lot of empty sessions in my mongo database (using mongolab), probably on every request (or very often). Here is an example:
{
"_id": "oThxLcz3PtztDWVxcKZvoADC",
"session": "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{}}",
"expires": {
"$date": "2013-07-10T22:45:52.383Z"
}
}
As you can see, there is no user defined in the object. I read in another issue that it might be a difference of time between the server and the client so the cookies are expiring instantly but that's not the case, the sessions are working fine. Any idea how to have only a line every time somebody logs in or signs up? I don't want to pay extra storage on my database.
For info, I am using 2 dynos on Heroku and mongolab and my set up is:
app.use(express.session({ secret: 'secretkey',
store: new MongoStore({
url:'mongodb://db:user#link:27468/dbname'
})
}));
I can't help you debug that issue, but I can suggest using connect-redis instead. The Redistogo nano instance on Heroku is free, and should support automatically expiring unused sessions so that you won't need a pricier option.

Resources