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});
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
}))
I'm looking for sessionstore for production app because I have error message:
Warning: connect.session() MemoryStore is not designed for a
production environment, as it will leak memory, and will not scale
past a single process
My code:
var express = require('express');
var ECT = require('ect');
var cookieParser = require('cookie-parser');
var compress = require('compression');
var session = require('express-session');
var bodyParser = require('body-parser');
var _ = require('lodash');
var passport = require('passport');
var expressValidator = require('express-validator');
var connectAssets = require('connect-assets');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(methodOverride());
app.use(cookieParser());
app.use(session({
resave: true,
saveUninitialized: true,
secret: secrets.sessionSecret,
}));
app.use(passport.initialize());
app.use(passport.session());
var app = module.exports = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(app.get('port'), function() {
console.log('Express server listening on port %d in %s mode', app.get('port'), app.get('env'));
});
module.exports = app;
I don't know what is the best solution for my production app. I'm using sequelize as ORM with PostgreSQL.
I will be very grateful with any opinion.
Though an answer has been accepted, I think a more elaborated answer is in order, so that people who actually want to use Express with PostgreSQL for consistent session storage can have a proper reference.
Express has the session module to handle the sessions though it defaults to in-memory storage that is suitable for development stages but not for production
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.
So for PostgreSQL there is a dedicated simple connector called connect pg simple
Once you import the connect-pg-simple you . need to pass it the session import like this:
const session = require('express-session')
const pgSession = require('connect-pg-simple')(session)
When you add the session as middleware you'll have to pass it its settings
app.use(session(sessionConfig))
and in your sessionConfig, this would be where you set all your session parameters you need to add a store option that would look like this (adding the full set of options though for the matter at hand just note the store option):
const sessionConfig = {
store: new pgSession({
pool: sessionDBaccess,
tableName: 'session'
}),
name: 'SID',
secret: randomString.generate({
length: 14,
charset: 'alphanumeric'
}),
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7,
aameSite: true,
secure: false // ENABLE ONLY ON HTTPS
}}
The new instance of pgSesision takes two options, the pool which is the config setup to access the PostgreSQL DB and the table name.
The DB connection setting should look like this:
const sessionDBaccess = new sessionPool({
user: DB_USER,
password: DB_PASS,
host: DB_HOST,
port: DB_PORT,
database: DB_NAME})
Also note that the session pool must be initiated:
const sessionPool = require('pg').Pool
I got it working with connect-pg-simple.
Create a session table with the provided table.sql, and pass in a connection string or an object.
If you have just to store session you can use redis or maybe mongoDB if you want persistence.
I have an Express 4 app setup to have sessions.
// Sessions
app.use(cookieParser());
app.use(session({ secret: "some-secret" }));
// Signup
app.post("/signup", function (req, res) {
create_user(req.body.user, function (err, user_id) {
req.session.user_id = user_id;
res.redirect("/admin");
});
});
When I submit the form, it saves the user_id to the req.session. However, when I restart the server, the session is gone.
Why isn't it persisting? Am I missing some configuration?
The default session store for express-session is MemoryStore, which as the name suggests, stores sessions in memory only. If you need persistence, there are many session stores available for Express. Some examples:
Cookie store
Redis store
MongoDB store
CouchDB store
Riak store
memcached store
leveldb store
MySQL store
PostgreSQL store
Firebase store
For a updated and more complete list visit Compatible Session Stores.
#mscdex answer is great but in case you are looking for code samples. Here is one with connect-mongo which should work fine if you mongodb and mongoose.
Install the package:
npm i connect-mongo
require the package:
const session = require('express-session'); // You must have express-sessions installed
const MongoStore = require('connect-mongo')(session)
Now configure the session:
app.use(
session({
secret: "mysecrets",
resave: false,
saveUninitialized: false,
store: new MongoStore({
mongooseConnection: mongoose.connection,
ttl: 14 * 24 * 60 * 60
}),
})
);
Again this assumes you are using mongoose and have the connection configured.
If you did everything right, it should work just fine.
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"