NodeJS - Framework for stateless sessions? - node.js

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

Related

How to secure my react app api with csurf?

I am trying to add csrf protection to my react app but I am getting an error Invalid token all the time
import bodyParser from 'body-parser';
import cookieSession from 'cookie-session';
import passport from 'passport';
import csrf from 'csurf'
import config from '../../config'
import AuthRoutes from "./routes/AuthRoutes";
/* Test only */
import cookieParser from 'cookie-parser';
const session = cookieSession({
maxAge:24 * 60 * 60 * 1000,
keys:[config.COOKIE_KEY],
name:'authentication',
});
export default app => {
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(session);
app.use(passport.initialize());
app.use(passport.session());
/* Test */
app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.use(function (err, req, res, next) {
if (err.code !== 'EBADCSRFTOKEN') return next(err)
// handle CSRF token errors here
res.status(403)
res.send('form tampered with')
})
/*Passport Config*/
require('../../services');
/* Register, Login these are routes i want to protect */
AuthRoutes(app);
}
You need to:
1. Configure csrf library on the server. This ensures the library will send the first piece of data attached to the server responses.
2. Use csrf library on the server to generate the second piece of data and attach it to the server response (e.g. HTML form sent to the client). After this step is completed the server response will carry two pieces of CSRF data.
3. On the client take the second piece of data and insert it into the request you are about to send (e.g. the form you are about to submit).
Step 1
So far only the step (1) has been completed. You asked the csrf library to send the first piece of data as a cookie. You could have used a better configuration:
app.use(csrf({cookie: {
httpOnly: true,
}}));
It ensures the browser won't allow any JS on the client to touch the first piece of data inside the cookie which is good because there is no legit reason for any script to know what is inside this cookie. Later on, in production and when you use HTTPS, you can optionally add secure: true to the above configuration to make the server refuse to send this cookie over connections that are not secure.
Step 2
To get the second piece of data call csrfToken(). The csrf middleware added another property to Request object for your convenience so it can be called like this: const secondPiece = req.csrfToken(). You can put the second piece of data into the server responce in any way or manner you like: into another cookie with an arbitrary name (except for the _csrf name already taken by the step 1 cookie) or into HTTP header named as you like.
For example this code will put it into another cookie:
res.cookie('XSRF-TOKEN', req.csrfToken());
Step 3
On the client write JS to get the second piece of data and put it into one of the predefined places/locations (inside the request to be sent to the server) where csrf middleware searches for it by default.
Just in case, any solutions doesn't work.
I just had days of debugging caused by incorrect naming of the cookie. Make sure to name your cookie XSRF-COOKIE(take note it uses - symbol) because I incorrectly named mine using underscore XSRF_COOKIE and this bit my ass for days.

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

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.

everyauth and a connect-couchdb session store - how to generate req.user?

Using everyauth on a Express/Cradle/CouchDB/Coffee-SCript stack, I am interested in finding out how to generate the req.user helper in express, through the
everyauth.everymodule.findUserById (userId, callback) ->
function. Don't mind the coffee script, I can handle raw JS ;) Anyhow, there is a persistent session store CouchDB like this:
exp = require 'express'
sessionDB = require('connect-couchdb')(exp)
... snip ...
app.use exp.session {secret: 'softw', store: new sessionDB({
host: config.sessionDBHost,
name: config.sessionDBName,
reapInterval: 600000,
compactInterval: 300000})}
I do have access to the req.session.auth object, but I would like to get the req.user done as well. How would I access the session store from within the findUserById function?

Resources