Logging in to one Express app destroys session in other (same server) - node.js

I have two separate Express 4.x apps running on the same server machine (different ports), sharing a MongoDB instance. They both use different databases and have different session secrets.
I am able to log into application A or B individually without issue. My session is maintained and all is well. However, if I am logged into A and then log into B, my session in A is destroyed (and vice versa).
Both applications have near-identical local auth. Their serializeUser and deserializeUser is very primitive (following the Passport docs almost to the tee).
It seems that when logging into A then B, req.session.passport is destroyed, causing req.user to not serialize properly on app A and the session is considered invalid.
I'm starting to think it has to do with the fact both apps run on the same machine (thus domain), differing only by a port.

express-session : Simple session middleware for Express in Node.js. To use this you have to include this package like this.
var session = require('express-session');
To install this package, run the following command:
$ npm install express-session
How to use this in Express, following code is given:
app.use(session({
secret: 'secretkey',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
By default, the name of the session ID cookie to set in the response (and read from in the request) is connect.sid. To overwrite this use the following :
app.use(session({
name: 'cookiename',
secret: 'secretkey',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
For more reference see this link - https://www.npmjs.com/package/express-session
Note:- Put your express-session statement in your application app.js before app.use(passport.session()) statement.
Hope this will help to solve your query !!

const mongoose = require('mongoose'),
timestamps = require('mongoose-timestamp');
var Schema = mongoose.Schema;
const Sessions = new mongoose.Schema({
expires : {
type : String,
default : ""
},
session : {
type : Schema.Types.Mixed,
default : {}
}
}, { collection: 'sessions' })
Sessions.plugin(timestamps)
module.exports = mongoose.model('sessions', Sessions);
//require schema
const Sessions = require('sessions');
//remove session by id
Sessions.remove({"session.user._id":user._id}
).exec(console.log)

you have to mention the different names for each session in different projects while running at different ports. by default, it will be connect.sid for all projects.
for example:-
project A running in port 3000 -
project B running in port 5000 -
while running these projects at the same time by default, they will have the same session name so they will get clashes in the authentication. so you must use different session names for each project.

Related

cookie confusion with session storage

I am using the following Node.js code to create a 'session store' to keep user information. These text files are kept in a folder called "session-store":
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(session({
store: new FileStore({path: './session-store'}),
// using FileStore with express-session
// as the store method, replacing the default memory store
secret: 'secret_key',
name: 'myadmin',
resave: false,
saveUninitialized: false,
cookie: { maxAge: 60000, httpOnly: true, secure: false }
}));
app.get('/', function (req, res) {
if (req.session.views) {
req.session.views++;
} else {
req.session.views = 1;
}
});
My text file which contains the session information seems to generate properly. However I have some confusion regarding its proper usage. In my cookie (.txt) file, it reports the "views" correctly, such as ""views":1". However if I define another variable, such as "req.session.broadcast = String(req.body.usr);" I do not see this information in my text file...why would this not be inclusive? Is this because the .txt file containing the cookie session storage information is generated only on the initial 'route' (i.e. the "app.get('/', function (req, res) {...do stuff}") and no other place in the Node.js code? (NOTE: I have "req.session.broadcast" set in a different route other than the 'homepage' route...which I guess is when the cookie file gets generated...possibly?).
I am simply attempting to properly manage users...therefore I want to be able to have certain session variables properly set and tracked for each unique user browser.
Are the "req.session.user" and/or req.session variable(s) 'hard coded' variables? I believe they get set when the browser is directed at the webpage, however how can they be used to terminate a session? Do they automatically become null if the user closes their browser (using the "x" in the right top corner) OR if the user directs their browser to another webpage...?
Any help with these questions and any other advice would be GREATLY appreciated.

How to set redis express-session store with loopback?

I'm using loopback 3. Wich connector is better loopback-connect-redis or loopback-kv-redis and how to configure store attribute in express-session object after adding the datasouce .
I tried :
store: app.dataSources.myDataSourceName but I got an error "store.get is not a function" so I tried :
store: app.dataSources.myDataSourceName).KeyValueAccessObject
I don't get any error but I don't have any key,value on redis. Thank you
Loopback (which I'm not hugely familiar with, admittedly) is based on Express (which I am familiar with).
I believe you should just use the express-sessions as in normal Express.
const
...
session = require('express-session'),
RedisStore = require('connect-redis')(session),
redis = require('redis'),
rs = new RedisStore({ client : redis.createClient([connection your info]) })
});
session({
secret : 'foobar',
store : rs
});
Then you would register it in your middleware.json file in the session phase.

multiple Session requests getting overwritten in nodejs application

I am trying to implement session using nodejs. However i am unable to handle multiple requests in sessions.
Example:
If user1 login, data loads.
If user2 login, user 1 data is getting overwritten with user2.
So on refreshing user1 page, again user2 data getting loaded.
var session = require('express-session');
app.use(session({
secret: "secterd13",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
//Set the session data in login page.
sessionObj = req.session;
sessionObj.Location = "Location1";
//Get in dashboard.
console.log(sessionObj.Location);
Where you do sessionObj = req.session you are creating a global variable and reassigning it on every user. The last user to connect to your server will always overwrite this. If you plan to pass the session data to a template engine, you can use 'res.render('view', { session: req.session })simply and the session variable will be available in your template. Or you can set the session as global usingres.locals.myVariable = req.sessionandmyVariable` will be available in your template.
I encountered the same issue and I used req.session for solving it.
I assigned unique_id to each request when it arrives at the server. It worked successfully for me.
Here's my solution:
var user_count = 0;
/*********** Authentication request ***********/
var handleAuthRequest = function(req, res) {
var unique_id = ++user_count;
/********* setting unique id to each request session *********/
req.session.unique_id = unique_id;
res.redirect("/user/db_op");
}
app.get("/home/get_data", handleAuthRequest);

connect-redis in Nodejs

I have nodejs/express/redis/express-session in use in my nodejs application (express 4.x)
The redis initializing is done by connect-redis/session framework under hood. So far it works. Now I need to use redis to store other data in addition to session, and world like to have a new store other than the session store. Is it just one store possible?
And is it possible to use the redis client initialized by connect-redis/session if only one store is possible? how to get it?
Thanks for the help!
The code now is:
var express = require('express');
var session = require('express-session');
// pass the express to the connect redis module
// allowing it to inherit from session.Store
var RedisStore = require('connect-redis')(session);
....
// Populates req.session
app.use(session({
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
secret: 'keyboard cat',
store: new RedisStore
}));
You'll actually want to initialize a new client for anything else, as the session library is handling it's own client under the hood.
You should most likely import the redis library itself, make your own client, and use that for all future requests / etc.
When I put following code after the code above, I got error
"myRedis Error-> Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED". It seems it is not allowed to init a new Redis instance.
So is there a way to have new client from connect-redis?
var myRedis = require('redis'); // additional redis store
var myRedisCli = myRedis.createClient();
myRedisCli.on('error', function (err) {
console.log('myRedis Error-> ' + err);
});

Shared Sessions between Node Apps?

I currently have two separate node apps running on two different ports but share the same backend data store. I need to share users sessions between the two apps so that when a user logs into through one app, their session is available and they appear to logged into the other app. In this case, its' a public facing website and an administrative backend.
Our setup is the following:
node with express
passport is being used to handle auth with Local Strategy
we're using connect-redis to allow us to share sessions via redis.
our domains look like this: www.mydomain.com and adm.mydomain.com
The config for for session stuff (and redis) is the same for both apps:
session: {
options: {
secret: "my secret",
cookie: {
domain: "mydomain.com",
maxAge:1000*60*60*24
}
},
redis: {
host: 'my host',
maxAge: 86400000,
secret: "my secret"
}
}
The config for session stuff in app.js looks like this:
if ( app.settings.env === "production" ) {
session.options.store = new RedisStore(session.redis);
}
app.use(express.session(session.options));
app.use(passport.initialize());
app.use(passport.session({ secret: 'a different secret' }));
What I expect it to do: Allow us to see the same session id in the cookie between the two apps.
So my question is: How do I set up express, redis and passport so that you can have sessions shared across different subdomains?
Maybe a bit outdated, but at this time, Express-session can recognise domain option for cookie. According to source:
function session(options){
var options = options || {}
// name - previously "options.key"
, name = options.name || options.key || 'connect.sid'
, store = options.store || new MemoryStore
, cookie = options.cookie || {}
...
And this is for setting cookie:
var Cookie = module.exports = function Cookie(options) {
this.path = '/';
this.maxAge = null;
this.httpOnly = true;
if (options) merge(this, options);
...
So, something like this will work for current 1.10.1 master:
secret: "my secret",
cookie: {
domain: "mydomain.com",
Express-session does not seem to recognize the "domain" option for cookies hence your problem. The cookie storing the session id is automatically tied to the domain for each app and so it cannot be shared.
One option is to write your own single-sign-on module to share sessions across webapps. It would probably live in an app.use() declaration fairly early in the execution order and would simply create a separate cookie (which would be cross-domain), create a separate SSO session id, and store the SSO id in this new cookie. Afterwards, you simply cross-populate req.session and req.sso-session as needed.

Resources