Question: How can I confirm that the session values from my simple node.js test app are being stored in Redis?
Backstory: I am hosting this app on a Digital Ocean server running Centos. Redis is installed on the server and I confirmed that it was turned on using the ping command. With the app running I checked the / endpoint in Chrome and the route fired as expected. Everything seems fine but how do I check to see if Redis is actually storing the session values?
$ redis-cli ping // PONG
app.js
const express = require('express');
const session = require('express-session');
const redis = require('redis');
const RedisStore = require('connect-redis')(session);
const app = express();
const redisClient = redis.createClient();
const PORT = 8080;
app.set('view engine', 'ejs');
app.use(session({
name: 'randomWord',
resave: false,
saveUninitialized: false,
secret: 'superSecretKey',
store: new RedisStore({ client: redisClient }),
cookie: {
sameSite: true,
secure: false,
}
}));
app.get('/', function(req, res, next) {
req.session.counter += 1;
res.render('index', { output: req.session.counter });
});
app.listen(PORT, () => console.log( `app listening on port ${PORT}` ));
from index.ejs
<h1><%= output %></h1>
There's multiple ways to verify it, but probably the simpler is to connect to your Redis instance and have a look at the commands going through. An example:
$ redis-cli
$ monitor
With the monitor command, Redis will print every single command reaching the server. With your Express server up and running, try logging in, or whatever action triggers a session creation in your system. Watch the logs printed by the monitor command, and you'll easily be able to tell whether the sessions are being stored in Redis.
For further validation, stop the Express instance and run it again; you should still have the session available, as it's not stored in memory, but instead using Redis.
I work with app, that already has its own infrastructure. The task is to integrate session-cookie mechanism. I spent a lot of time to understand why cookies doesn’t set on client side.
I. Briefly.
App settings:
Server: NodeJS
Port: 8081
Client: VueJS
Port: 8088
I use module "express-session" to initialize session mechanism on server side and send cookies to client. Client hasn’t set cookies.
II. Details:
Server’s root file is index.js.
I do the following in it:
Plug in express module:
const express = require('express')
Plug in cors module:
const cors = require('cors')
Add cors settings:
app.use(cors({
origin: 'http://localhost:8088',
credentials: true
}))
Then I initialize session in user.js file and receive client’s connects:
Plug in express-session module:
const session = require('express-session')
Plug in routing by express.Router():
const router = express.Router()
Add session settings:
const EIGHT_HOURS = 1000 * 60 * 60 * 2
const {
SESS_NAME = 'sid',
SESS_LIFETIME = EIGHT_HOURS,
SESS_SECRET = 'test',
NODE_ENV = 'development'
} = process.env
const IN_PROD = NODE_ENV === 'production'
Initialize session:
router.use(session({
name: SESS_NAME,
resave: false,
saveUninitialized: false,
secret: SESS_SECRET,
cookie: {
maxAge: SESS_LIFETIME,
sameSite: false,
// Must have HTTPS to work 'secret:true'
secure: IN_PROD
}
}))
Receive client queries by router.post()
App client side consists of a lot of files. Client send data to NodeJS server by Axios module.
I read several articles by this theme and I guess that server side settings, which I made, are enough for work session-cookie mechanism. That means, that problem is on Vue side.
What I made:
I set in all files, where Axios send data to server, parameter withCredentials in true value (withCredentials: true) to pass CORS restrictions. This didn’t help
App in production has other URLs for accessing the production NodeJS server. I set develop NodeJS server URL in all client side files. This didn’t help
Read this article: Vue forum. From this article I understood, that need to solve this problem by axios.interceptors (StackOverFlow forum). I supposed that if this setting set on one of the client’s side pages, may be cookies should work at least on this page. This didn’t help.
Tried to set setting like this:
axios.defaults.withCredentials = true
And that:
axios.interceptors.request.use( function (config) {
console.log('Main interceptor success')
config.withCredentials = true;
return config;
},
function(error) {
// Do something with request error
console.log('Main interceptor error')
return Promise.reject(error);
}
)
This didn’t help
Please, tell me in which direction I should move? Is that right, that on client side on absolutely all pages must be axios.defaults.withCredentials = true setting to initialize cookies mechanism? What details I miss? If I set session-cookies from scratch the mechanism works.
I resolve this issue. I need to look for cookie storage in another browser place:
Chrome server cookie storage
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 switched from memorystore to using Redis and I also use MongoDB locally.
Similar posts that I have read are not relevant or helpfull.
Basicly, if the router function try's to set a value to req.session the node app shuts down.
I am new to Redis, so maybe it is something obvious that I don't see?
// in app
var app = express();
var cookieParser = express.cookieParser('secret');
app.configure(function () {
app.use(express.bodyParser());
app.use(cookieParser);
app.use(express.session({secret: 'secret', store: othermodule.getSessionStore()}));
// othermodule
var RedisStore = require('connect-redis')(express);
var sessionStore = new RedisStore({
host: 'localhost',
port: 6379,
db: 2,
pass: 'RedisPASS'});
thanks
Try removing the password in your options you pass to RedisStore.
If you want you can require the clients to give a password when connecting. But by default no password is required for clients to connect. If no password is required and you give a password, the client will try authenticating using the given password which will cause a connection failure. The fallback to using no password is not allowed at the client. Because of which you were getting session as undefined.
See here and here for configuring passwords.
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"