Store Node JS express sessions using Azure Redis Cache - node.js

I have tried to build an Express 4 Web App using Azure. I found on several articles that I can store the sessions in Azure Redis Cache. However, how should I connect my web app to the redis cache?
var session = require('express-session');
var redis = require('redis');
var RedisStore = require('connect-redis')(session);
var client = redis.createClient(6380, 'MyHost', { auth_pass: 'MyPass', tls: { servername: 'MyHostName' } });
app.use(session({
secret: 'keyboard cat',
key: 'sid',
resave: false,
saveUninitialized: false,
store: new RedisStore(client);
}));
But then it returns an error when I run the app. Saying
TypeError: this.client.unref is not a function
How can I solve this? Thanks!

You might make a mistake in RedisStore constructor.
Change the following line of code store: new RedisStore(client); as below:
store: new RedisStore({client: client});

Related

How to solve 'connect-redis' error 'A client must be directly provided to the RedisStore'

During the maintenance process, of a NodeJS backend application, I updated the connect-redis package to the last version 6.1.3 and bumped in the following error
Error: A client must be directly provided to the RedisStore
I tried to check online but I didn't understand what change I needed to make in my code to make it work
import redisStore from 'connect-redis';
import session from 'express-session';
import config from '../config/conf';
const RedisStore = redisStore(session);
const sessionStore = new RedisStore({ url: process.env.SESSION_REDIS_URL });
const sessionConfig = {
name: 'os.sid',
store: sessionStore,
saveUninitialized: false,
resave: false,
secret: config.sessionSecret,
secure: config.isProduction,
cookie: {
path: '/',
httpOnly: true,
secure: config.isProduction,
maxAge: null,
},
};
I tried to read this but I cannot figure out what to change in my code with the imports
connec-redis post about the issue

Redis Store + Express Session

I notice that some of the project will use redis store and express session to save the user session
For example:
const session = require('express-session');
var redis = require("redis");
var redisStore = require('connect-redis')(session);
var client = redis.createClient();
var app = express();
app.use(session({
secret: 'scret',
store: new redisStore({
host: '127.0.0.1',
port: 6379,
client: client,
ttl : 7200
}),
saveUninitialized: true,
// rolling: false,
resave: true,
cookie: {
maxAge: 2 * 60 * 60 * 1000
}
}));
What is the reason that we need to use these two Session Management function at the same time?
express-session can be set up with different "stores" to save session data.
MemoryStore comes with the package express-session.
The authors of express-session warn about this default store.
Warning The default server-side session storage, MemoryStore, is
purposely not designed for a production environment. It will leak
memory under most conditions, does not scale past a single process,
and is meant for debugging and developing.
Redis is one of the compatible session stores and in this case is used "as a replacement" of a default store.

Can we store session in Database?

Can we store session in database Mysql not in memory using passport module.
I am using nodejs, express and mysql
Thanks
Passport module doesn't provide sessions to your application, it uses connect or express session.
connect/express sessions may (and should!) be persistent and there are plenty of session stores available on npm.
With a quick search I found two implementations of connect/express mysql session store:
connect-mysql
express-mysql-session
Just take any one of them and use as your session store with express-session (or conncect.session):
var express = require('express');
var session = require('express-session');
var SessionStore = require('express-mysql-session')
var app = express();
var sessionStore = new SessionStore(/*options*/);
app.use(session({
key: 'session_cookie_name',
secret: 'session_cookie_secret',
store: sessionStore,
resave: true,
saveUninitialized: true
}))

Why does node express req.session disappear with redis?

Node.js express sessions work perfectly for me with this code:
var express = require("express");
var app = express();
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
cookie: {maxAge: pembapp.dayInMilliseconds * 180},
secret: 'mysecret',
key: 'mykey'
}));
I can access req.session.whatever with no problem.
Now I want to use redis to store session data in case a server restart is needed, so the code becomes this:
var express = require("express");
var app = express();
var RedisStore = require('connect-redis')(express);
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
cookie: {maxAge: pembapp.dayInMilliseconds * 180},
secret: 'mysecret',
key: 'mykey',
store: new RedisStore({
host: 'localhost',
port: 6379,
db: 2,
prefix: 'myprefix',
pass: 'mypasswd'
})
}));
When I add the redis code, req.session is now undefined! Can't figure this out for the life of me. Why would req.sesion "disappear" when I add a redis store for sessions???
I think we can close this one out. Perhaps I wasn't connecting to redis when req.session was undefined. I did find that I needed to explicitly call req.session.save() when using redis, which wasn't needed without redis.
Judging from the questions I've seen out there, ff someone could create a clear node.js example using redis-connect for persistent sessions, for node newbies, starting from scratch, I think you'd make a bunch of folks very happy.
Are you sure it is connecting to the Redis database?

How to save and retrieve session from Redis

I am trying to integrate Redis sessions into my authentication system written in Node.js.
I have been able to successfully set up Redis server, connect-redis and Express server.
Here is my setup (just the important bit):
var express = require("express");
var RedisStore = require("connect-redis")(express);
var redis = require("redis").createClient();
app.use(express.cookieParser());
app.use(express.session({
secret: "thisismysecretkey",
store: new RedisStore({ host: 'localhost', port: 6379, client: redis })
}));
Now... How do I actually create, read and destroy the session? I am aware that that is probably extremely simple. I have read tons of articles on how to setup connect-redis and many questions here on SO, but I swear each one stops on just the configuration and does not explain how to actually use it...
That should be all there is to it. You access the session in your route handlers via req.session. The sessions are created, saved, and destroyed automatically.
If you need to manually create a new session for a user, call req.session.regenerate().
If you need to save it manually, you can call req.session.save().
If you need to destroy it manually, you can call req.session.destroy().
See the Connect documentation for the full list of methods and properties.
Consider this code.
var express = require('express');
var redis = require("redis");
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var bodyParser = require('body-parser');
var client = redis.createClient();
var app = express();
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(session({
secret: 'ssshhhhh',
// create new redis store.
store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 260}),
saveUninitialized: false,
resave: false
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.get('/',function(req,res){
// create new session object.
if(req.session.key) {
// if email key is sent redirect.
res.redirect('/admin');
} else {
// else go to home page.
res.render('index.html');
}
});
app.post('/login',function(req,res){
// when user login set the key to redis.
req.session.key=req.body.email;
res.end('done');
});
app.get('/logout',function(req,res){
req.session.destroy(function(err){
if(err){
console.log(err);
} else {
res.redirect('/');
}
});
});
app.listen(3000,function(){
console.log("App Started on PORT 3000");
});
So you need to install connect-redis and pass your express-session instance to it.
Then in middleware initialize redisStore with server details like this.
app.use(session({
secret: 'ssshhhhh',
// create new redis store.
store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 260}),
saveUninitialized: false,
resave: false
}));
I put ttl to 260, you can increase. After TTL reaches its limits, it will automatically delete the redis key.
In routers you can use req.session variable to SET, EDIT or DESTROY the session.
One more thing...
If you want custom cookie i.e not as same as in your Redis store you can use cookie-parser to set cookie secrets.
Hope it helps.
link : https://codeforgeek.com/2015/07/using-redis-to-handle-session-in-node-js/
You can also use the Redis monitor tool to see all the action in real time! When you refresh your app you will see the data appear in the console window.
redis-cli monitor
Sample Output for Sessions using tj/connect-redis
1538704759.924701 [0 unix:/tmp/redis.sock] "expire" "sess:F9x-YgbgXu1g7RG8tFlkwY3RV0JzHgCh" "3600"
1538704759.131285 [0 unix:/tmp/redis.sock] "get" "sess:F9x-YgbgXu1g7RG8tFlkwY3RV0JzHgCh"
1538704787.179318 [0 unix:/tmp/redis.sock] "set" "sess:Hl3LPbOBdKO44SG4zQHFn2gfdiWTwzWW" "{\"cookie\":{\"originalMaxAge\":3600000,\"expires\":\"2018-10-05T02:59:47.178Z\",\"secure\":true,\"httpOnly\":true,\"domain\":\".indospace.io\",\"path\":\"/\"},\"path\":\"/\",\"userAgent\":{\"family\":\"NewRelicPingerBot\",\"major\":\"1\",\"minor\":\"0\",\"patch\":\"0\",\"device\":{\"family\":\"Other\",\"major\":\"0\",\"minor\":\"0\",\"patch\":\"0\"},\"os\":{\"family\":\"Other\",\"major\":\"0\",\"minor\":\"0\",\"patch\":\"0\"}},\"ip\":\"184.73.237.85\",\"page_not_found_count\":0,\"city\":\"Ashburn\",\"state\":\"VA\",\"city_state\":\"Ashburn, VA\",\"zip\":\"20149\",\"latitude\":39.0481,\"longitude\":-77.4728,\"country\":\"US\"}" "EX" "3599"
1538704787.179318 [0 unix:/tmp/redis.sock] "set" "sess:Hl3LPbOBdKO44SG4zQHFn2gfdiWTwzWW" "{\"cookie\":{\"originalMaxAge\":3600000,\"expires\":\"2018-10-05T02:59:47.178Z\",\"secure\":true,\"httpOnly\":true,\"domain\":\".indospace.io\",\"path\":\"/\"},\"path\":\"/\",\"userAgent\":{\"family\":\"NewRelicPingerBot\",\"major\":\"1\",\"minor\":\"0\",\"patch\":\"0\",\"device\":{\"family\":\"Other\",\"major\":\"0\",\"minor\":\"0\",\"patch\":\"0\"},\"os\":{\"family\":\"Other\",\"major\":\"0\",\"minor\":\"0\",\"patch\":\"0\"}},\"ip\":\"184.73.237.85\",\"page_not_found_count\":0,\"city\":\"Ashburn\",\"state\":\"VA\",\"city_state\":\"Ashburn, VA\",\"zip\":\"20149\",\"latitude\":39.0481,\"longitude\":-77.4728,\"country\":\"US\"}" "EX" "3599"

Resources