Session id being same for different client Nodejs - node.js

Currently we are setting up session in the cookie using express-session with passport.js and connect-redis to store the data in redis.
I have multiple node server serving requests. For each request without a session, I am creating a new session. Sometimes, an existing session id is being assigned to a new request. Before creating a unique session, I am checking whether the cookie is there...if it is, then I am not creating a new session. But while doing so, we are seeing that same session id being shared with different client.
How do I know its being same?
First user tries to login, it gives successful login and sets up the session and gives the correct information about the user profile.
Second user tries to login, it gives a successful login but sets the session as the previous i.e. first user's session , hence the second user sees the first user info in the profile section.
Code for the Session implementation:
function sessionImplementation() {
return function (req, res, next) {
if(/ucompany=s%3A/.test(req.headers['cookie'])){
var cookie = req.headers['cookie'].split("ucompany=s%3A");
var zCookie = cookie[1].split(".");
var genid = zCookie[0];
return session({
genid:function () {
return genid;
},
store: redis,
cookie: {
maxAge: new Date(Date.now() + (7 * 24 * 60 * 60 * 1000))
},
secret: 'ucomp123',
resave: false,
name: "ucompany",
saveUninitialized: true
})(req, res, next)
}
return session({
store: redis,
cookie: {
maxAge: new Date(Date.now() + (7 * 24 * 60 * 60 * 1000))
},
secret: 'ucomp123',
resave: false,
name: "ucompany",
saveUninitialized: true
})(req, res, next)
}
}
What is the issue and how can I fix it?
Update 1
As per #robertklep I have modified my code.
var express = require('express');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var app = express();
app.use(bodyParser.json());// to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compress());
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//app.use(cookieParser());
var redis = new RedisStore({
host:config.redis.url,
port:config.redis.port,
prefix:'sess-'+new Date().getDate()+'-'+(new Date().getMonth()+1)+'-'+new Date().getFullYear()+':'
});
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
store: redis,
cookie: {
expires: new Date(Date.now() + (7 * 24 * 60 * 60 * 1000)),
maxAge:7 * 24 * 60 * 60 * 1000
},
secret: 'ucomp123',
resave: false,
name: "ucomapny",
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

There are several issues with your code:
instead of letting express-session handle the session cookies, you're trying to handle them yourself;
you're instantiating the session middleware for every single request, which is a waste of resources and may also cause problems (I haven't dug into express-session deep enough to make any definitive claims on that);
maxAge (for the cookie) should not be a date but a number (the number of milliseconds from now that the cookie should remain valid); you're confusing it with expires, which is used to set a point-in-time;
The regular way of using it looks like this:
var session = require('express-session');
var express = require('express');
var app = express();
...
app.use(session({
store : redis,
cookie : { maxAge : 7 * 24 * 60 * 60 * 1000 },
secret : 'ucomp123',
name : 'ucompany',
resave : false,
saveUninitialized : true
});

where is a genid ?
you have to generate it yourself. Use uuid package

Related

How to avoid conform resubmission page while pressing back button from home page?

I'm trying to prevent the "Confirm resubmission" page from appearing after logging in and pressing back, but I'm not sure how to implement it in the code I provided below. Can anyone help me with this?
this is my code for user router part
const nocache = require('nocache');
const user_route = express();
//session
const session = require("express-session");
const config = require("../config/config")
user_route.use(session({
secret: config.sessionSecret,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 24 * 60 * 60 * 1000, // 24 hours
},
}));
const auth = require("../middleware/auth");
user_route.use(nocache());
// view engine setup
user_route.set('view engine', 'ejs');
user_route.set('views', './views/users');
const bodyParser = require("body-parser");
user_route.use(bodyParser.json());
user_route.use(bodyParser.urlencoded({ extended: true }))
// handling user requests through userController module
const userController = require("../controllers/userController");
user_route.get('/register', auth.isLogout, userController.loadRegister);
user_route.post('/register', userController.insertUser);
user_route.get('/', auth.isLogout, userController.loginLoad)
user_route.get('/login', auth.isLogout, userController.loginLoad)
user_route.post('/login', userController.verifyLogin);
user_route.get('/home', auth.isLogin, userController.loadHome);
user_route.get('/logout', auth.isLogin, userController.userLogout);
module.exports = user_route;```

Update session variable in Node

I set a session variable called user upon login:
req.session.authenticated_user = user;
When I set the session again later it doesn't update:
req.session.authenticated_user = somenewvalue;
This will still contain the original value of user. App module:
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var redisClient = redis.createClient();
const sessionMiddleware = session({ secret: 'foo' });
app.use(session({
store: new redisStore({ client: redisClient }),
secret: 'secretsession',
resave: false,
saveUninitialized: true,
cookie: { secure: false, sameSite: true, expires: 7200000 }
}))
app.use('/users', sessionChecker, usersRouter);
My router:
var express = require('express');
var router = express.Router();
var user_controller = require('../controllers/userController')
/* GET user update. */
router.get('/user_login/login', user_controller.user_login_get);
/* POST user update. */
router.post('/user_login/login', user_controller.user_login_post);
/* GET user update. */
router.get('/:username/update', user_controller.user_update_get);
/* POST user update. */
router.post('/:username/update', user_controller.user_update_post);
How can I update a session variable in node?
Answered here: Sessions won't save in Node.js without req.session.save()
req.session won't update automatically if req is a Post request. For Post requests, one must call req.session.save() unless data is sent out through res.send, res.redirect, etc.

req.flash() requires session

I got the problem on a route (register) :
TypeError: req.flash is not a function
at /Users/laurent/Projects/perso/express-live-stream/server/routes/register.js:11:32
Setup in app.js
const Session = require('express-session');
const flash = require('connect-flash');
app.use(require('cookie-parser')());
app.use(Session({
store: new FileStore({
path : './server/sessions'
}),
secret: config.server.secret,
cookie: {maxAge: Date().now + (60 * 1000 * 30) } ,
resave: false,
saveUninitialized: false
}));
app.use(flash());
Router (routes/register.js)
const express = require('express'),
router = express.Router(),
passport = require('passport');
router.get('/',
require('connect-ensure-login').ensureLoggedOut(),
(req, res) => {
res.render('register', {
user : null,
errors : {
username : req.flash('username'), <== problem here (line 11)
email : req.flash('email')
}
});
});
It seems my setup is ok as flash messages are stored in sessions.
I checked before in Google but didn't find anything
Thanks
Laurent
Fixed the problem
wrong order I should declare router before flash

How are connect-mongo MongoStore sessions actually saved?

I implemented sessions using Passport, but for storing sessions I tried connect-mongo using a mongoose connection.
This is my code (sessions part):
var express = require('express')
var mongodb = require('mongodb')
var mongoose = require('mongoose')
var bodyParser = require('body-parser')
var cookie = require('cookie-parser')
var connect = require('connect')
var passport = require('passport')
//var flash = require('connect-flash')
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var LocalStrategy = require('passport-local').Strategy;
var app = express()
var BSON = mongodb.BSONPure
app.use(express.static(__dirname+"/public"))
app.use(bodyParser())
app.use(cookie())
app.use(connect.session({ secret: 'ilovescotchscotchyscotchscotch' }));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect('mongodb://localhost/psicologosTuxtepecDB')
var Schema = mongoose.Schema
var userCredential = new Schema({
username: String,
password: String
}, {
collection: 'members'
})
var userCredentials = mongoose.model('members', userCredential)
app.use(session({
secret: 'ziKologiia',
clear_interval: 900,
cookie: { maxAge: 2 * 60 * 60 * 1000 },
store: new MongoStore({
db : mongoose.connection.db
})
}));
Something I doubt if it would be counterproductive is that app.use(connect.session({ secret: 'ilovescotchscotchyscotchscotch' })) is usingconnect module but the MongoStore configuration is set upon a express-session variable. However, deleting first causes app to not work good (won't authenticate/redirect).
So, about my question title. Where is that session stored? I really thought I could go to my Mongo database and find any collection storing it.
How can I find such sessions at backend (Mongo) and even at the applicacion as Java Script objects?
connect-mongo stores sessions in the "sessions" collection by default. They should be there and visible in the mongo shell or any GUI tool like robomongo. Yes, it is created by default. I would pass in the mongooose_connection option instead of db.
From the docs:
mongoose_connection in the form: someMongooseDb.connections[0] to use an existing mongoose connection. (optional)
One thing you should do is replace
app.use(connect.session({ secret: 'ilovescotchscotchyscotchscotch' }));
with your
app.use(session({
secret: 'ziKologiia',
clear_interval: 900,
cookie: { maxAge: 2 * 60 * 60 * 1000 },
store: new MongoStore({
db: mongoose.connection.db
});
}));
Updated Method of MongoClient:
import session from "express-session";
import MongoStore from "connect-mongo";
app.use(
session({
secret: "Your Key",
cookie: {
maxAge: 60000 * 60 * 24, //1Sec * 1H * 24 = 1 Day
secure: process.env.NODE_ENV !== "production"? false : true
},
resave: true,
saveUninitialized: true,
store: MongoStore.create({ mongoUrl: process.env.MongoDBUrl}),
})
);

Setting up sessions on express app on multiple dynos heroku app

I have implemented some user authentication on a single Heroku dyno using express (node.js)+ mongodb and everything is working fine. However, when I increase the number of dynos (more than 1), I cannot login, I keep being redirected on my login page, meaning my session hasn't been set. Here is my code:
checkCookies = function(req, res, next) {
if(req.session.user){
res.locals.user = req.session.user;
next();
}
else{
res.redirect('/login');
}
};
app.use(express.cookieParser());
app.use(express.session({ secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
cookie: {httpOnly: true, maxAge:14*24*60*60*1000}
}));
What is the best solution to handle shared session on express/node.js using mongodb?
The above answers are misleading in that they imply you can't share cookie based sessions across multiple dynos on Heroku.
I'm able to to use cookie based sessions across multiple dynos if I use cookie-session as opposed to express-session. What's missing from the first post in this thread is the secret value is NOT passed to the cookie parser. This means that node will assign a random hash to the parser each time the process restarts or when a new dyno spins up.
Doing the following works for me:
app.use(express.cookieParser('0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK'))
app.use(express.session({
secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
cookie: { httpOnly: true, maxAge: 14 * 24 * 60 * 60 * 1000 },
}))
connect-mongo should meet your needs: https://github.com/kcbanner/connect-mongo
Use connect-mongo module with express.
var http = require('http'),
express = require('express'),
session = require('connect-mongo')(express)
And then in your workers setup session to store externally. Code below will use session from mongo, cookies and extra headers in order to allow cross-domain and jsonp.
app.configure(function() {
app.use(express.cookieParser());
app.use(express.session({
store: new session({
db: 'sessions'
}),
secret: 'yoursecret',
cookie: {
path: '/',
maxAge: 1000 * 60 * 60 * 24 // 1 day
}
}));
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
app.set('jsonp callback', true);
});
For anyone looking for a quick copy/paste solution that is a bit more updated then basically follow the link Dan posted above or just use my snippet below:
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose'); // if using mongoose
mongoose.connect(connectionOptions); // if using mongoose
app.use(cookieParser());
app.use(session({
store: new MongoStore({mongooseConnection: mongoose.connection}),
secret: '0GBlJZ9EKBt2Zbi2flRPvztczCewBxXK',
cookie: {
path: '/',
maxAge: 1000 * 60 * 60 * 24 // 1 day
}
}));

Resources