How to destroy the session (store)? - node.js

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.

Related

Multiple redis instances for multiple NodeJS servers

After a bit of research, I came to the conclusion that I can run multiple instances of Redis on my CentOS server for each NodeJS server I run (I use Redis to store sessions).
I have followed these instructions and both instances are running properly on two different ports.
On my NodeJS servers, I configured Redis as follows:
import * as session from "express-session";
var RedisStore = require('connect-redis')(session);
var redis = require("redis").createClient();
app.use(session(
{
secret: secret,
store: new RedisStore({ host: 'localhost', port: 6379, client: redis }),
cookie: { maxAge: 12 * 3600000 },
resave: true, saveUninitialized: true
}
));
One with port 6379 and the other with 6380.
I use req.session.regenerate to register a session.
Both login systems work perfectly individually. However, when I load anything on one application, the sessions of the other application are deleted (and need to be re-logged in).
What am I missing here?
The problem looks like it is the "session store" in Express and not your usage of Redis.
From the express session documentation:
NOTE be careful to generate unique IDs so your sessions do not conflict.
app.use(session({
genid: function(req) {
return genuuid() // use UUIDs for session IDs
},
secret: 'keyboard cat'
}))
Name: The name of the session ID cookie to set in the response (and read from in the request).
The default value is 'connect.sid'.
Specifically this warning explains your problem:
Note if you have multiple apps running on the same hostname (this is
just the name, i.e. localhost or 127.0.0.1; different schemes and
ports do not name a different hostname), then you need to separate the
session cookies from each other. The simplest method is to simply set
different names per app.

Node.js Handle session with database

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
})
}));

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

Using Redis for session store doesn't seem to work

adapting an existing app to Express 4.4.x
Trying to implement redis session store, using the following code:
var express = require('express');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var redis = require('redis').createClient();
app.use(session({
store: new RedisStore({
host: '1.1.1.1',
port: 1234,
prefix: 'yourprefix:',
client: redis
}),
secret: '.......',
resave: true,
saveUninitialized: true
}));
However, when I run this there is no key stored in redis and I cannot call req.session. I'm sure it's something really simple I've missed or included something in the code which is restricting it. Could also be redis settings?
Thanks
Ok, I just got lost in the documentation. Difficult to keep track of express-session, redis, connect-redis and entirely remember the difference between everything.
The simple solution was:
var redis = require('redis').createClient(port, host, auth);
Now it works. I believe I was able to use .createClient(); when the redis server was hosted locally, however now we've moved to a dedicated redis server - these attributes are required.
Thanks, hope this helps somebody else!

Session updates not persisting between requests - nodejs/expressjs/redis/heroku

I'm using redis for storing my sessions in expressjs. It works fine when running locally and even works most of the time when deployed on heroku. The problem is that regularly (when deployed on heroku) I see my session updates being lost.
e.g. a user logs in to my website, and I add their user object to the session:
req.session.user = user;
however (sometimes) when I try and retrieve the object moments later (in a different request) it isn't there
//sometimes this is empty, even though I've just set it
var currentUser = req.session.user;
I initialise the session store as follows
if (process.env.REDISTOGO_URL) {
console.log('Connecting to redis:' + process.env.REDISTOGO_URL);
var rtg = require('url').parse(process.env.REDISTOGO_URL);
var redis = require('redis').createClient(rtg.port, rtg.hostname);
redis.auth(rtg.auth.split(':')[1]);
} else {
console.log('Connecting to local redis');
var redis = require('redis').createClient();
}
//sessions
app.use(express.cookieParser('secret key for cookie monster')); //used by session
var RedisStore = require('connect-redis')(express);
app.use(express.session({
store: new RedisStore({
client: redis
})
}));
Any ideas? Do I need to do some kind of flushing (or explicit saving) of the session data?
I'm going to hijack this ancient question and let you guys in on how I solved the problem.
TL;DR
You have probably copied the REDIS_URL value from your Heroku app config to your local .env file some time ago. Heroku changes that value over time and that has now actually happened.
The solution is to copy the new REDIS_URL value from your Heroku app config to your local .env file or use another Redis instance for local development.
What you probably already tried
Probably your sessions were working a few days ago and you tried and verified all the usual suspects in order to fix this sudden problem.
cookie: { secure: false }
'trust proxy'
credentials: 'include' + Access-Control-Allow-Credentials header set to true
All to no avail. Finally, when you remove the RedisStore bit from the session config, sessions are working again.
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
// ...
server.set('trust proxy', 1);
server.use(
session({
// store: new RedisStore({
// url: process.env.REDIS_URL,
// }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: {
path: '/',
httpOnly: true,
secure: false,
maxAge: null,
},
})
);
What's happening?
Sometime later I understood how removing the Redis store solved the problem. I was using a REDIS_URL in my local .env file that was provided by my Heroku app config. And I learned that the REDIS_URL on the Heroku app may change over time.
In order for Heroku to manage this add-on for you and respond to a
variety of operational situations, the REDIS config vars may change at
any time. Relying on the config var outside of your Heroku app may
result in you having to re-copy the value if it changes.
(emphasis mine)
So in my case that had actually happened and my local .env file still had the old REDIS_URL value. In effect, the session store could not be created, because it tried connecting to a service that isn't there. That's why removing RedisStore and thus falling back to the default MemoryStore fixed the problem.
Prevent reoccurrence
I created an account at redislabs.com and created a free Redis instance. That url I now use in my local .env file. That url doesn't change (I hope).

Resources