Handle and Design Session Part in Non-Auth Web App - node.js

I'm creating a web app (Node.js+Express+Mongoose), which is really simple in authentication. It's more like a one-time use app, so there's no user name and password that need user to signup or login.
User A could use the web app when he enter the index page. And he will get a UUID (some ID that looks like a UUID :) ). I want to setup a session module, so that my user A won't get a new UUID when he return to the app in a short time.
And the reason I don't want User A get new UUID is: he can have private talk with other User B/C. And the chat stuff needs his/their UUID to store and retrieve.
Thank you very much for all of your help!

It sounds like you've already understand what is required based on your question
When the user vists the index page, in this case let's say it's '/', the page generates a uuid and stores it in the session like so (unless they already have an id assigned to them):
var uuid = require('uuid');
var mongoose = require('mongoose');
var session = require('express-session');
// Basic mongoose session setup
mongoose.connect(connectionOptions);
app.use(session({
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
// Example index route
app.get('/', function (req, res) {
if(!req.session.uid) {
// No uid is set for this user
req.session.uid = uuid.v1();
// do something
} else {
// uid already exists
}
}

Related

express-session: How to renew ssid but preserve data?

I use node.js and express.js to implement my web server.
I use express-session module (https://github.com/expressjs/session) to handle web sessions and connect-redis (https://github.com/tj/connect-redis) for session store. I believe it does not relate to the type of the store but in case you ask I told you.
After user login and doing some sensitive data changed, eg. change the password, I'd like to renew the ssid. So I use req.session.regenerate(). However, after the function call, all other session data lost. How can I preserve the session data after renewing the ssid?
What actual behaviour:
req.session.userId = 100;
req.session.regenerate(function(err) {
// will have a new session here
console.log(req.session.userId); // undefined
});
What I want:
req.session.userId = 100;
req.session.regenerate(function(err) {
// will have a new session here
console.log(req.session.userId); // 100
});
Below is what I have done. It works but is it the correct way to do that?
var sessionData = req.session;
req.session.regenerate(function(err) {
// will have a new session here
req.session = sessionData;
});
It cannot be done in current version 1.15.6. The feature will be added in the future.
https://github.com/expressjs/session/issues/425
It is a good workaround. Maybe better use Object.assign:
var sessionData = req.session;
req.session.regenerate((err) => {
Object.assign(req.session, sessionData);
});

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

Setting Global / Local Vars

I'm just getting started with Node and I'm running into issues setting variables. In the example below, it appears the value of random will be the same for every user because it's being set on app start.
var random = math.Random();
app.post('/api/whatever/', function(req, res) {
console.log(random);
});
Using a local variable will mean that the value of random changes every time a post request is made:
app.post('/api/whatever/', function(req, res) {
var random = math.Random();
console.log(random);
});
What I'm trying to figure out is how to set the value of random once per user / session (i.e. the first time a user makes a call to /api/whatever). I have other configuration variables to set after the first request, so it may be better to just trigger an init() function. The problem would be the same though.
Your global variable could hold an object whose keys are session ID and values are whatever session-specific information you want - such as your random number.
To get the session ID, see this question: How can I find the session Id when using express / connect and a session store?
Use the express-session module:
npm install express-session
Here's an example:
...
var session = require('express-session');
app.use(session({secret: '1234567890QWERTY'}));
app.get('/api/whatever/', function(req, res) {
if(req.session.random) {
res.send('Your random key is: ' + req.session.random);
} else {
req.session.random = Math.random();
// Set anything else you want in req.session ...
}
});

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.

Resources