Node.js saving session using Redis store - node.js

I am facing an issue with handling session using latest version of Express, Node.js.
My requirement is to store users email id in /login route, and need to get that email id thought out
all routes like /home. But email id is not printing in /home route with my current code. Your help is much appreciate.
My demo code is here
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.set('port',process.env.PORT || 3000);
app.use(cookieParser());
app.use(session({
resave: false,
saveUninitialized: false,
store: new RedisStore({
host: 'localhost',
port: 6379
}),
secret: 'some string/hash secret'
}));
var counter=0;
app.get('/login', function(request, response){
//adding some value to request.session
request.session.email = 'jak#amt.in';
console.log('sessionID', request.sessionID)
response.send('email: '+request.session.email);
});
app.get('/home', function (request, response) {
console.log('home login', request.session.email); // Email not priting here
console.log('sessionID - home', request.sessionID); // Session ID is showing
response.send('home');
});
if (!module.parent) {
console.info('Listening ', process.env.PORT || 5000);
app.listen(process.env.PORT || 5000);
}
module.exports = app;
I am getting following error
"ReplyError: ERR wrong number of arguments for 'set' command
at parseError (/home/dibeesh/obpnode6/testproject/node_modules/redis/node_modules/redis-parser/lib/parser.js:161:12)
at parseType (/home/dibeesh/obpnode6/testproject/node_modules/redis/node_modules/redis-parser/lib/parser.js:222:14)"

Make sure your redis server is running when you run your app.

Related

redis freezes node server when connected

I am trying to use redis to store sessions with express-session. Here is the code:
//Imports
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const session = require('express-session');
const logger = require('morgan');
//Connect to Redis
const redis = require('redis');
let RedisStore = require('connect-redis')(session);
let redisClient = redis.createClient();
redisClient.connect();
redisClient.on('connect', () => console.log('Connected to Redis..'));
app.use(
session({
store: new RedisStore({ client: redisClient }),
saveUninitialized: false,
secret: 'keyboard cat',
resave: false,
})
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(logger('dev'));
app.get('/', function (req, res) {
var body = '';
console.log(req.session);
if (req.session.views) {
++req.session.views;
} else {
req.session.views = 1;
body += '<p>First time visiting? view this page in several browsers :)</p>';
}
res.send(
body + '<p>viewed <strong>' + req.session.views + '</strong> times.</p>'
);
});
app.listen(3000, () => console.log('App is listening on port 3000'));
Whenever I start my application, it freezes. I have checked the redis-cli and pinged it with the response 'PONG'. redis-server is starting just fine. Whenever I remove the following lines:
redisClient.connect();
redisClient.on('connect', () => console.log('Connected to Redis..'));
the app crashes whenever I hit the "/" route. But if I had those lines in, the app just hangs there and doesn't do anything. I checked the docs here and they said you need to connect before any command:
https://github.com/redis/node-redis/blob/HEAD/docs/v3-to-v4.md#no-auto-connect
And the code I'm running is right from the connect-redis npm page:
https://www.npmjs.com/package/connect-redis
I'm not sure why the server is freezing. It works fine if I remove store from the session so it's definitely something to do with redis but on the node side. The redis server is running fine on the localhost. Any suggestions?
**UPDATE
I checked the connect-redis repo issues and I found that someone else is having the same problem as me. The problem will be resolved in the next commit:
https://github.com/tj/connect-redis/issues/336
This is currently a known issue. Currently connect-redis is not compatible with the latest version of node redis.
https://github.com/tj/connect-redis/issues/336
Add the following to your client to fix this issue until patched:
const client = createClient({
legacyMode: true
});

Troubles with express and socket.io sessions

I seem to not be able to share sessions between express and socket io . It works when on localhost but not when on my server. There is something I am missing.
The data I store in socket.handshake.session ('age' here) is not saved on the express side.
My app.js goes like this:
var cookieParser = require('cookie-parser');
var session = require('express-session');
var app = express();
app.use(cookieParser()); // read cookies (needed for auth)
var sessionMiddleware = session({
secret: 'keyboard cat',
resave: true,
name: 'sessionId',
saveUninitialized: true,
cookie: { maxAge: 60000 },
// store: new redisStore({ host: 'localhost', port: 6379, client: redisClient, ttl: 86400 }),
});
app.use(sessionMiddleware);
app.set("sessionMW", sessionMiddleware);
module.exports = app;
My bin\www goes like this:
var app = require('../app');
var debug = require('debug')('testserver:server');
var http = require('http');
var sharedsession = require("express-socket.io-session");
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var session = app.get("sessionMW")
io.use(sharedsession(session, {autosave:true}));
server.listen(port);
I then have a serverEvent.js that goes like this:
var serverEvents = module.exports = function(io){
io.sockets.on('connection', function (socket) {
...
...
...
socket.on('updateAgeSession', function (message) {
socket.handshake.session.age = "18";
socket.handshake.session.save();
console.log(socket.handshake.session);
})
})
}
And finaly I have this index.js for my routes:
module.exports = function (app, passport) {
// show the home page (will also have our login links)
app.get('/', function (req, res, next) {
res.cookie('mycookies', 'express');
res.cookie('age', req.session.age);
cookie1= req.cookies;
console.log(req.session);
console.log(req.sessionID);
console.log(req.sessionStore.sessions);
if (req.session.views) {
req.session.views++;
console.log(req.session.views);
} else {
req.session.views = 1
console.log(req.session.views);
}
if(req.session.age){
console.log("OOOOOOOOOOOOOOOOOO");
} else {
console.log("XXXXXXXXXXXXXXXXXXXXXX");
}
res.render('homePage'); // ejs template
});
}
So my problem is that after I enter that Im over 18 when I refresh the page , the req.session.age will be undefined, but only when my code runs on server, it does work on localhost. I dont get it.
Please help
For anyone that might have got the same problem I had, here is the solution :
I also have a client side code that goes like this :
var socket = io.connect("http://ip:3000");
var globalVar = [];
// Sent on connection/searchValidatedFromClient by server
socket.on("loadHomePageFromServer", function(message) {
...}
Problem was io.connect("http://ip:3000");.
By changing it to io.connect("http://namesite.com"); or io.connect("http://ip:80");, it works!

Session variable is not available across routes

I am facing this problem from long time and finally I decided to post it here.
I am storing the session variable in one route and when I try to access it from other route it is not defined.
server.js file
var express=require('express');
app=express();
var port=process.env.PORT || 8080;
var mongoose=require('mongoose');
var router=express.Router();
var appRoutes=require('./routes/api')(router);
var session=require('express-session');
var MongoStore=require('connect-mongo')(session);
app.use(bodyParser.urlencoded({extended:true}));
app.use(session({
secret:'hardik',
saveUninitialized: true,
resave: true,
store: new MongoStore({mongooseConnection:mongoose.connection})
}));
app.listen(port,function(){
console.log('running on port '+port);
});
api.js
router.post('/authenticate',function(req,res){
var token=jwt.sign({
email:req.body.email
},secret);
var profile=req.body.profile;
req.session.token=token;
console.log(req.session);
console.log(req.session.token);
}
and after this it will show the token if I log just below that line but in any other routes if I try to log it, it gives undefined.
any help is invited.
If you are using passport after user login you can match all route with * and store the session with req.locals
app.get('*', function(req, res, next){
res.locals.user = req.user || null;
next();
});
Add this line before you start your server

Using RedisStore in nodejs / expressjs

I'm trying get access to session data in express so I thought I would try declaring a connect-redis session store when configuring express. However, I cannot see why this doesn't work:
var express = require('express');
var http = require('http');
var RedisStore = require('connect-redis')(express);
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));
//app.use(express.session({ secret: "keyboard cat" }));
app.use(app.router);
app.get('/', function(req, res){
console.log('/');
req.session.items = [ 'apple', 'orange' ];
res.end('items configured');
});
app.get('/items', function(req, res){
console.log('/items: ', req.session.items);
var s = JSON.stringify(req.session.items);
res.end('items: ' + s);
});
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
The '/' route simply configures items with the session.
The '/items' route displays the list of items in the session.
It works using the standard expressjs session store.
It doesn't work using connect-redis (req.session is undefined)
I'm assuming the redis store will be instantiated and destroyed as the app loads/unloads (or do I need it running outside of node/express app?)
Any ideas?
req.session will be undefined if RedisStore can't connect to your Redis server. So it's either not running, or it's not running on the default location that RedisStore is looking for it (127.0.0.1:6379).
In case of the latter, you can configure the location using the options argument to the RedisStore constructor.
Give this a try.
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");
});
link : https://codeforgeek.com/2015/07/using-redis-to-handle-session-in-node-js/
You should invoke RedisStore constructor (with ())
app.use(express.session({ secret: "keyboard cat", store: new RedisStore()}));

Passport.socketio: handshake is always unauthorized

I'm a Node-beginner and have the following problem. I use express, socket.io and passport as well as passport.socketio and a MongoStore.
I need to authenticate socket.io with passport (I use passport.socketio for this), but the handshake is always unauthorized even after successfull login. Here is my code so far:
var http = require('http')
var socketio = require('socket.io')
var express = require('express')
var stylus = require('stylus')
var passport = require('passport')
var passportSocketIo = require('passport.socketio')
var LocalStrategy = require('passport-local').Strategy
var mongo = require('mongoskin')
var MongoStore = require('connect-mongo')(express)
var DB = mongo.db('mongo://127.0.0.1/accounts', {safe:false})
DB.bind('accounts')
DB.bind('SessionStore')
SessionStore = new MongoStore({ db: 'SessionStore' })
var app = express()
app.configure(function () {
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.use(express.cookieParser())
app.use(express.bodyParser())
app.use(express.session({
secret: 'somekey',
store: SessionStore
}));
app.use(passport.initialize())
app.use(passport.session())
app.use(app.router)
})
Here is where I login:
app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login_failed',
failureFlash: false }))
And here I try to access a page ('/content'), for which I need authorization:
app.get('/content', ensureAuthenticated, function(req, res){
res.render('content', { user: req.user })
})
var server = http.createServer(app).listen(5050)
var io = socketio.listen(server)
io.set('authorization', passportSocketIo.authorize({
cookieParser: express.cookieParser,
key: 'express.sid',
secret: 'somekey',
store: SessionStore,
fail: function(data, accept) {
accept(null, false);
},
success: function(data, accept) {
accept(null, true);
}
}))
But if a client now tries to access '/content', the server always responds 'handshake unauthorized':
// on client side
socket = io.connect('http://localhost:5050');
// on server side
io.sockets.on( 'connection', function( socket ) {
console.log(socket.handshake.user._id)
}
-> handshake unauthorized
Does anyone know what I do wrong here?
Yes that's an issue known since two years and not resolve yet :
https://github.com/LearnBoost/socket.io/issues/545
As koenigsbier said in this github issue :
In my client side I had var socket =
io.connect('http://localhost:8080'); and it's works only if you put
localhost:8080 in your browser.
I changed it by var socket = io.connect('http://127.0.0.1:8080');
and now it works with localhost:8080 and 127.0.0.1:8080 in your
browser.
It's clearly a bug, why socket.io should accept address mapping just
in one way? localhost is localhost and is the same as 127.0.0.1
On client side, try to put 127.0.0.1 instead of localhost
You need to use:
key: 'connect.sid',
instead of
key: 'express.sid',
for the key. Check out the cookie in your browser, you won't see express.sid, but connect.sid will have a value. The only other difference that I see between yours and my working example is I set a var to express.cookieParser and then use that both in app config and in io.set authorization.
var cookieParser = express.cookieParser();

Resources