cookie confusion with session storage - node.js

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.

Related

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);

Differentiate express-session sessions in chrome tabs

I am trying to assign to each user a "req.session.pseudo", but when I try to connect in different tabs, it display me the same session.
Here is an exemple with a "req.session.page_views".
Here is the code :
var express = require('express');
var session = require('express-session');
var app = express();
app.use(session({
secret: 'ssshhhhh',
resave: false,
saveUninitialized: true
}));
app.get('/', function(req, res) {
if(req.session.page_views){
req.session.page_views++;
res.send("You visited this page " + req.session.page_views + " times");
} else {
req.session.page_views = 1;
res.send("Welcome to this page for the first time!");
}
});
the result on my first tab:
Welcome to this page for the first time!
the result on my second tab:
You visited this page 2 times
I hope to have been clear about my problem. Thank you.
Tabs share cookies, and cookies are used to identify sessions. If tab #1 gets a session cookie, tab #2 will send that same session cookie to the server, so both tabs share the same session.
You can create one session in your browser's "regular" mode, and one session in its "private" (incognito) mode, but that's about it (tabs created in each mode also share the same cookie for that mode, at least in Chrome, so you can't create multiple incognito windows/tabs and create a new session in each).
Possibly, there are extensions for your favorite browser that may be used to create multiple sessions concurrently, but you'd have to search for those.

Not cookie based session management in node.js

I am looking for a non-cookie based session management in node.js, something like pass a parameter in the URL like &session_id=. It will know that a session has expired when a request comes with an session_id. I've looked at connect library, but it looks that it is cookie based only.
Warning
Passing the session id as a GET parameter is considered bad practice. Why? It is dangerous because people don't usually care about session id and they will probably publish/share links with their session ids inside.
It's also a problem because when a user clicks an external link on your web, and goes to another site, that new site will be able to see the session_id in the referrer link.
So I don't think it is a good idea. Cookies are more secure.
Have a look at: Session Hijacking
For every request you receive, you will get all of the client cookies accordingly.
You can also set client cookies in the response HTTP headers using "Set-Cookie."
Using a GET parameter is unsafe. Any user could accidently share their session ID, but if you want 100% security, I'd share session IDs via cookies, and I would use HTTPS to prevent snoopers from stealing cookies.
You can use localstorage or sessionStorage..
almost same as cookie
not a cookie
better than a cookie!
More info: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
It's very -very- easy to use... in Js for example:
<script>
// check if Storage is avaible
if(typeof(Storage)!=="undefined") {
// Save data to local storage (no exiparion date)
localStorage.setItem("name_always", "bxx");
// Save data to the current session (removes when the tab is closed)
sessionStorage.setItem("name_now", "bxx");
} else {
// No Storage support...
}
// Access to stored data
alert( "For only now, my name is: " + sessionStorage.getItem("name_now"));
alert( "Every day, my name is: " + localStorage.getItem("name_always"));
</script>
Tags: javascript html5 local-storage session-storage
You can use sessions with a store in node.js. For example, you have express application and want to use session like system in your webapp. You can use connect-mongo module for this. This will let you store your session in db. In your app.js
var express = require('express'),
, mongoStore = require('connect-mongo')(express);
var app = express();
app.configure('all', function () {
app.use(express.session({
secret: "terces",
cookie: { maxAge: 24 * 60 * 60 * 1000 },
store: new mongoStore({
url: your_db_url
})
}));
app.use(function(req, res, next) {
res.locals.session = req.session;
next();
});
});
With basic code above, you have session in express that you can use it in your controllers and views directly. In your controller;
app.post('/blog/create/?', function(req, res, next) {
if (!req.session.user) {
next("You need to login in order to create blog!");
}
});
In your view, you can use session.user in order to generate profile menu for example.

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.

Node.js - Session doesn't persist through res.redirect()

I'm (almost) successfully using Node.js with Express and Redis to handle sessions.
The problem I'm having is that the session is not kept when I use res.redirect().
Here is how I can see it :
req.session.username = username.toString();
console.log(req.session);
res.redirect('/home');
The console.log() prints :
{ lastAccess: 1322579131762,
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 29 Nov 2011 15:06:31 GMT,
originalMaxAge: 60000 },
username: 'admin' }
Now, here is the following code :
app.get('/home', [app.requireLogin], function(req, res, next) {
// Not showing the rest as it's not even getting there
// Instead, here is what's interesting
app.requireLogin = function(req, res, next) {
console.log(req.session);
This console.log() prints out this :
{ lastAccess: 1322579131775,
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 29 Nov 2011 15:06:31 GMT,
originalMaxAge: 60000 } }
Clearly, the 'username' object has disappeared. The session has not kept it, and just rebuilt a new one.
How can I solve this? Don't hesitate if you need any information.
Here is the code where I set the session management :
app.configure(function() {
// Defines the view folder and engine used.
this.set('views', path.join(__dirname, 'views'));
this.set('view engine', 'ejs');
// Allow parsing form data
this.use(express.bodyParser());
// Allow parsing cookies from request headers
this.use(express.cookieParser());
// Session management
this.use(express.session({
// Private crypting key
secret: 'keyboard cat',
store: new RedisStore,
cookie: {
maxAge: 60000
}
}));
this.use(app.router);
});
Here is the whole project (I mean, parts of it), on gist : https://gist.github.com/c8ed0f2cc858942c4c3b (ignore the properties of the rendered views)
Alright, I found the solution. The problem is that the time in maxAge was added to the current date. So, in the browser side, the cookie was set to expire at the GMT time shown.
The problem was the following : I use a virtual machine to test node.js, and, you know... sometimes, you suspend your machine.
Well, what happened is that the machine's time was two days late. So, whenever the cookie was set on the server side, the client side thought the cookie was already expired, since my host machine was not two days late.
Another stupid outcome.
Did you try with different browsers ? Are you keeping the same session id between page redirects ?
You could add req.session.cookie.expires = false; before redirecting...
Your code looks pretty solid, but is there a reason you're using client.end()? It forcibly closes the redis connection and is not clean. I don't think you need it at all:
https://github.com/mranney/node_redis/issues/74
I am not sure about the underlying architecture for connect-redis, but I'm wondering if calling client.end is what's resetting your sessions. What happens if you take those out?
I was having a similar problem in that I was setting something on the session that was not persisting outside the app.get() it was set in.
My problem turned out to be that I was not doing a res.redirect() at the end of my app.get(). Looks like I was setting something on a request object and then allowing it to get garbage collected.
I added a res.redirect( '/nextmethod' ) and the data persists just fine.
Surely you need to save that session in some way, this might work.
req.session.regenerate(function(){
req.session.username = username.toString();
res.redirect('/home');
});

Resources