Not cookie based session management in node.js - 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.

Related

Keeping track of users history in express to make a 'back' button?

I'm making an express app and I want to include a 'back' button in the app UI that does basically exactly what the browser back button does.
I tried holding an array variable in the server that simply collects all of the URL params visited. For example, for the '/:lang' route ...
const browsingHistory = [];
app.get("/:lang", (req, res) => {
const lang = req.params.lang;
if (lang === "en" || lang === "fr") {
const templateVars = {
menuItems: db[lang].menuItems,
lang,
};
res.render("root", templateVars);
}
if (lang !== "favicon.ico") {
browsingHistory.push(lang);
console.log(`Browsing history: ${browsingHistory}`);
}
});
BUT I'm realizing this only works when locally hosted — once deployed, if there are multiple users simultaneously, how to keep track of each users' individual history? Or is there a better way of doing this?
Storing the browsing history will require user sessions. On each request, you will have to store the route that the user hits in their session variable.
In Express, this can be accomplished with the express-session library. You will want to initiate each session with some history property that begins as an empty array. Once express-session is set up, you can do something similar to the following
app.get("/:lang", (req, res) => {
const lang = req.params.lang;
req.session.history.push(lang);
...
});
app.get("/getMyPageHistory", (req, res) => {
res.send(req.session.history);
});
req.session will be unique for each user. So, you can store each user's unique history in this variable.
With that said, if you go down this route, you eventually will want some external session storage. By default, sessions are saved in your server's memory. This introduces a few issues that are explained in the express-session documentation. Here is their warning
Warning The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.
They provide a list of compatible session stores

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

Handle and Design Session Part in Non-Auth Web App

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
}
}

NodeJS - Framework for stateless sessions?

Is there a framework to support fully client-managed sessions? In other words, instead of storing just the signed pid in the cookie (as Express does), store all context... so that you can manage state across clusters without the requirement to persist.
There is express middleware which supports this:
https://github.com/expressjs/cookie-session
cookieSession()
Provides cookie-based sessions, and populates req.session. This middleware takes the following options:
name - cookie name defaulting to "session"
keys - list of secret keys to prevent tampering
secret - used as single key if keys are not specified
options - additional options such as secure, httpOnly, maxAge, etc.
Middleware:
var cookieSession = require('cookie-session')
...
app.use(cookieSession({
name: "my_session_cookie",
secret: "dont_tell_anybody_the_secret_and_change_it_often",
options: { ... }
));
app.use((req, res, next) => {
// set options on req.session before your response goes out
req.session.viewCount = (req.session.viewCount || 0) + 1;
res.end(`You viewed the page ${req.session.viewCount} times.`);
});
To clear a cookie simply assign the session to null before responding:
req.session = null

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