Session in nodejs - node.js

sorry for newby question, but can you explain me how to use sessions in nodeJS. I read a lot of articles in internet but I didn't success to implement something for my purpose (data is saving the session, but every new request session is empty), can you give example from the beginning how to initialize and how to use.
Purpose: when user do login in the system, I need to open session for him and every request that he will send in the future I need to check is his session exist?
I'm using express 4.x. I do it like:
// init session
app.use(cookieParser());
app.use(session({
secret : "yepiMobileSession",
resave : true,
key : "session",
store: mongooseSession(daoService.mongoose),
saveUninitialized : true
}));
// save user to the session
request.session[CONST.SESSION_USER] = user;
// Check login
function checkLogin(id){
var user = request.session[CONST.SESSION_USER];
if (user && request.params.clientData && user._id == id){
return true;
} else {
return false;
}
}

You can take a look at the following code. I think this will help you.
var app = require('express')(),
expressSession = require('express-session'),
cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(expressSession({
secret: 'mYsEcReTkEy',
resave: true,
saveUninitialized: true
}));// I haven't used the session store
//setting session
app.post('/login', function(req,res){
var id=12345;
req.session.userId = id;
res.send(200);
});
//getting session
app.get('/hello', function(req,res){
var id=req.session.userId;
console.log("Hello",id);
res.send(200);
});
But node server and client have to be in same domain.

Related

Session automatically destroys in Express JS, mongodb, Node js application

When i close the broswer, the session gets destroyed automatically. Following is the code in my app.js file.
const session = require('express-session');
const MongoSessions = require('connect-mongo')(session);
var mongo = require('mongodb').MongoClient;
var db_url = 'mongodb://localhost:27017/test';
app.use(session({
secret: '007',
resave: false,
saveUninitialized: false,
duration: 40*60 *1000,
activeDuration: 10*60*1000,
store: new MongoSessions({
url: db_url
})
}));
When user logs in , i store the user id of user in a session. When a user again accesses the system, it will redirect him to directly to home page. To check this:
exports.indexPage = function (req, res, next) {
if (req.session.userid == null) {
res.render('login');
} else {
res.render('index');
}
};
It works fine when i keep the browser open but close all tabs and again access the application. When i close the browser and again access the application, it redirects me to login page.
I'm not sure what duration and activeDuration are meant to be, but they aren't valid options for express-session.
Since you're not setting a maxAge value for the session cookie, it automatically becomes limited to the current browser session, meaning that it will be destroyed when you close the browser (as you already noticed).
To prevent that, configure a maximum age (in milliseconds):
app.use(session({
cookie : {
maxAge : 40 * 60 * 1000
},
secret: '007',
...
}));

How to check session in Node.js Express?

I try to check if session in Express 4 is exist:
if(req.session.user == undefined) {}
It gives me error:
Cannot read property 'user' of undefined
How I can check if exist value in session?
From the source:
How to use Express Session ?
Before heading to actual code, i want to put few words about
express-session module. to use this module, you must have to include
express in your project. Like for all packages, we have to first
include it.
server.js
var express = require('express');
var session = require('express-session');
var app = express();
After this, we have to initialize the session and we can do this by
using following.
app.use(session({secret: 'ssshhhhh'}));
Here ‘secret‘ is used for cookie handling etc but we have to put some
secret for managing Session in Express.
Now using ‘request‘ variable you can assign session to any variable.
Just like we do in PHP using $_SESSION variable. for e.g
var sess;
app.get('/',function(req,res){
sess=req.session;
/*
* Here we have assign the 'session' to 'sess'.
* Now we can create any number of session variable we want.
* in PHP we do as $_SESSION['var name'].
* Here we do like this.
*/
sess.email; // equivalent to $_SESSION['email'] in PHP.
sess.username; // equivalent to $_SESSION['username'] in PHP.
});
After creating Session variables like sess.email , we can check
whether this variable is set or not in other routers and can track the
Session easily.
Firstly it depends on the library you are using, maybe some libraries have utilities for that, I assume you're using express-session.
This is just Okay:
if(req.session.user){}
They are useless:
if(typeof req.session.user !== "undefined"){}
if(typeof req.session.user !== "undefined" || req.session.user === true){}
The reason: req.session is an object, just like normal objects:
var obj = { name : "adam" }
If you try to get obj.age which it doesn't exist and defined,
the getter function of the object, firstly check if it exists or not, if it's not, it wouldn't produce a fatal error and instead it assigns that property to undefined value.
That's cool, so obj.age get's undefined ( JS has undefined as a value type), moreover undefined is a falsy value (when you coerce it to boolean it becomes false, so it's falsy), which means you can simply check it in conditional statements like this: if(obj.age){}
You can't just create a session without any middleware (Im assuming this is what you've tried).
Read up on the express-session middleware docs, found here:
https://github.com/expressjs/session
Basic implementation example:
Create a session:
app.use(session({
genid: function(req) {
return genuuid() // use UUIDs for session IDs
},
secret: 'keyboard cat'
}))
To read a session:
// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
// Access the session as req.session
app.get('/', function(req, res, next) {
var sess = req.session
if (sess.views) {
sess.views++
res.setHeader('Content-Type', 'text/html')
res.write('<p>views: ' + sess.views + '</p>')
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>')
res.end()
} else {
sess.views = 1
res.end('welcome to the session demo. refresh!')
}
})
There are a number of tutorials you can find online, e.g:
https://www.thepolyglotdeveloper.com/2015/01/session-management-expressjs-web-application/
The issue you are facing is maybe you are not using the session middleware in ALL of your requests.
You can check it the following way :
Add this to all of your routes :
app.use(session({ secret: 'keyboard cat',resave:false,saveUninitialized:false, cookie: { maxAge: 60000 }}));
Authentication Route :
router.post('/', function(req, res, next) {
//login logic here
//if login successfull
req.session.user = username //your unique identifier
req.send("Hurray! logged in");
//else
req.send("Credentials error");
});
Check in any route:
router.get('/dashboard', function(req, res, next) {
if (req.session.user)
//do stuff here
else
//redirect to login page
})
This works :)

Express and redis session keeps returning undefined

I've been having problems trying to access stored session values! Once I've set the values and try access them from a new route, I get undefined! So basically I've got a login (POST) and in that request I set the session data, and then I have a show user details (POST) where I try and access the session data I've just stored.
Setup
// Setup express and needed modules #############################################
var express = require('express'),
session = require('express-session'),
cookieParser = require('cookie-parser'),
redis = require("redis"),
redisStore = require('connect-redis')(session),
bodyParser = require('body-parser');
var client = redis.createClient(), //CREATE REDIS CLIENT
app = express();
// Setup app
app.use(cookieParser('yoursecretcode'));
app.use(session(
{
secret: 'x',
store: new redisStore({
port: 6379,
client: client
}),
saveUninitialized: true, // don't create session until something stored,
resave: false // don't save session if unmodified
}
));
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
app.set('trust proxy', 1) // trust first proxy
So as you've seen my setup, you know I'm using express sessions and Redis. Below is where I'm setting the session values! If I print out the session values here it works, but then If I try and access the session data in another route it returns undefined.
Routes
I send a http post request and set the session data:
router.route('/login/').post(function(req, res) {
req.session.userId = req.body.uId;
req.session.name = req.body.uName;
// THIS PRINTS OUT IF I TRY AND ACCESS THE SESSION DATA HERE
console.log("THIS PRINTS OUT --> " + req.session.name);
});
So now that the session values have been set, I can go access them right, no, I get undefined each time I try and log them out.
router.route('/user/printoutuserdetails').post(function(req, res) {
// THESE RETURN UNDEFINED
console.log(req.session.userId);
console.log(req.session.uName);
console.log("THIS PRINTS OUT --> " + req.session.name);
});
Does anyone have any idea what's happening? I've tried everything and looked everywhere and can't seem to find a way to get it to work!
Solved:
The reason this wasn't was because you're not suppose to use sessions when using a RESTFUL api.

Set individual maxAge for sessions when using cookieSession() in connect/express

I am trying to use connect/express cookieSession() in order to store my node.js sessions in cookies (and thus, avoiding a server-side session store). This would help me to 'remember' the user when they log in and keep sessions alive even after server restarts.
I would like to do this with cookieSession():
app.use( express.cookieSession( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.session.cookie.maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
req.session.cookie.expires = false;
}
}
next();
});
However, this does not work, because req.session.cookie is undefined. I also tried the following, but it didn't seem to work:
app.use( express.session( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.cookies['connect.sess'].maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
rreq.cookies['connect.sess'].expires = false;
}
}
next();
});
Starting out with
app.use(express.cookieSession({ secret: config.server.cookieSecret }));
And changing it to
app.use(function(req, res, next) {
express.cookieSession({
secret: config.server.cookieSecret,
cookie: {
maxAge: req.param('remember') ? 20000 : 3000
},
})(req, res, next);
})
So, we create our own middleware, wrapped around the cookieSession middleware, changing the maxAge based on a param.
So, whenever you change the session you'll need to pass a remember in the body, query, or params( that's where req.param() looks ). In most cases, you only set a user_id to the session once, at login.
It's 3 seconds or 20 seconds to test and ensure it works.
And again, it might be not very helpful if you're setting stuff to your session a lot, but if you just set a user_id to session at login, this is all you need.
If you are setting lots of stuff to your session, you should know that data get passed around at every request, and you should save only the minimum to the session, like user_id, then look up the data you need for each request, to keep the overhead down on the user.
I think this does what you want:
// Using express.session instead of express.cookieSession
app.use(express.session({ secret : 'secret_key' }));
app.use( function (req, res, next) {
if ( req.method === 'POST' && req.url === '/login' ) {
if ( req.body.remember )
{
req.session.cookie.maxAge = 30*24*60*60*1000;
// needed to make the session `dirty` so the session middleware re-sets the cookie
req.session.random = Math.random();
}
else
{
req.session.cookie.expires = false;
}
}
next();
});
cookieSession does some funky stuff, like del req.session.cookie (not sure why).
You have to first set req.session.cookie so that you can set maxAge. Trying to use it before you set it gives req.session.cookie is undefined
express.cookieSession has default values which it accepts, see here. You should mention all the parameters you are going to use. You can set cookie via the following :
app.use(express.cookieSession({ secret: 'secret_key', cookie :{ path: '/', httpOnly: true, maxAge: 30*24*60*60*1000} });
A little late to the table but I thought this answer may help people going forward...
I was using cookie-session which doesn't create a cookie object on request.session. To properly implement rememberMe functionality using request.session.cookie I switched cookie-session to express-session and that solved everything. So now there is a cookie object on session and doing this inside of a request is possible...
npm install express-session
app.post('/login', function(request, response, next) {
passport.authenticate('local', function(err, user, info) {
if(err) return next(err);
if(!user) {
request.flash('loginMessage', info.message);
return response.redirect('/account/login');
}
request.login(user, function(err) {
if(err) return next(err);
if(request.body.rememberMe)
request.session.cookie.maxAge = 2592000000;
else
request.session.cookie.expires = false;
return response.redirect(options.redirect);
});
})(request, response, next);
});
This is also pretty late but it might help other people.
It seems like to me the best way to persist your session data is to store it in something like redis. The question asked for a way that didn't use server storage, but I think he was referring more to MemoryStore. Maybe not but either way this is what I did.
I used express-session and connect-redis
npm install -g connect-redis
npm install -g express-session
Then you configure stuff.
// session modules
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session')
var redisStore = require('connect-redis')(session); // this sets up Redis to work with your session cookies
var app = express();
Then you just initiate your session with the store option set to your redisStore.
The maxAge part sets the lifetime of each session to an hour, the session middleware resets it when it's accessed.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
store: new RedisStore({
host:'127.0.0.1',
port:6380,
prefix:'sess'
}),
cookie: {maxAge: 3600000 },
secret: 'session_secret'
}));
Now when a client connects, express should store the session data automatically in a Redis data structure. Since it's not just cached in memory, your server can crash and still have all the relevant session data still available at the IP address and and port specified.
Yummy seems to allow modifying cookies expiry after creation.

Session-only cookie for Express.js

http://www.javascriptkit.com/javatutors/cookie.shtml
Session-only cookies, on the other
hand, stores information in the
browser memory, and is available for
the duration of the browser session.
In other words, the data stored inside
a session cookie is available from the
time of storage until the browser is
closed. Moving from page to page
during this time does not erase the
data.
How can I achieve this using Express.js?
First off, that website is a horrible place to go.
Now on to the question.
What sessions actually are:
Data is stored on the server side.
A cookie is issued which contains an ID.
This ID gets send back to the server on every request, due to the fact that the browser sends the cookies.
Now the server can re-associate the ID in the cookie - commonly called Session ID or short SID - with the session data stored on the server.
Express.js has support for sessions built in.
What the example shows:
Setting up the Express.js middleware
Using a third-party store for saving the session data, in this case Redis (which IMO is overkill for your problem atm)
Installing Redis requires quite some work, but it's also possible to use Express.js's built-in memory store:
var express = require('express');
var app = express.createServer();
var MemoryStore = require('connect/middleware/session/memory');
app.use(express.bodyDecoder());
app.use(express.cookieDecoder());
app.use(express.session({ store: new MemoryStore({ reapInterval: 60000 * 10 }) }));
app.get('/', function(req, res){
req.session.visitCount = req.session.visitCount ? req.session.visitCount + 1 : 1;
res.send('You have visited this page ' + req.session.visitCount + ' times');
});
app.listen(4000);
This will simply keep track of how many times you visited the page, closed your browser and re-opend. The counts will still be there.
You can find more on the options of the MemoryStore, like maximum life time of a session, etc. here.
The following is what I wanted (sort of). When I close browser the information is gone.
var express = require('express');
var app = express.createServer();
var MemoryStore = require('connect/middleware/session/memory');
app.use(express.bodyDecoder());
app.use(express.cookieDecoder());
app.get('/remember', function(req, res) {
res.cookie('rememberme', 'yes', { expires: new Date() - 1, httpOnly: true });
});
app.get('/', function(req, res){
res.send('remember: ' + req.cookies.rememberme);
});
app.listen(4000, '127.0.0.1');
app.use(express.session({cookie: { path: '/', httpOnly: true, maxAge: null }, secret:'eeuqram'}));
The above works on IE8, Firefox and Chrome.
The important piece is maxAge:null
app.get('/remember', function(req, res) {
res.cookie('rememberme', 'yes', { expires: 0, httpOnly: true });
});
This will set session cookie. On browser close it will be erased!
Below is the updated code for Alfred's answer (session using Express.js).
var express = require('express');
var app = express.createServer();
var MemoryStore = require('/home/node/node_modules/connect/lib/middleware/session/memory');
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
key: 'some-key',
secret: 'some-We1rD sEEEEEcret!',
store: new MemoryStore({ reapInterval: 60000 * 10 })
}));
app.get('/', function(req, res) {
req.session.visitCount = req.session.visitCount ? req.session.visitCount + 1 : 1;
res.send('You have visited this page ' + req.session.visitCount + ' times');
});
app.listen(4000);
I know this is an old question but I'm adding an answer since all answers here seem to be either outdated, have security flaws or are just plain wrong.
As of now, express uses the MemoryStore by default, you don't need to explicitly handle that.
Also, as of now, the express-session's official readme page has a stark warning at the beginning to not use MemoryStore as the session store for production, quoting:
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.
For a list of stores, see compatible session stores.
Here's a simple solution with connect-mongodb-session if you want to use MongoDBStore for session storage:
import express from 'express';
import session from 'express-session';
import ConnectMongoDbSession from 'connect-mongodb-session';
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session({
secret: < COOKIE_SECRET >,
name: 'sessionId', // Don't use the default name, see http://expressjs.com/en/advanced/best-practice-security.html
cookie: {
httpOnly: true,
secure: true, // Remove this if you're not using HTTPS, but it will be a massive security flaw
sameSite: 'strict',
},
store: getStore(),
// Boilerplate options, see:
// * https://www.npmjs.com/package/express-session#resave
// * https://www.npmjs.com/package/express-session#saveuninitialized
resave: true,
saveUninitialized: true,
}));
function getStore() {
const MongoDBStore = ConnectMongoDbSession(session);
const store = new MongoDBStore({
uri: < DATABASE_URI >,
collection: < SESSION_COLLECTION_NAME >,
connectionOptions: {
useNewUrlParser: true,
useUnifiedTopology: true,
},
});
store.on('error', (error: any) => {
console.error(error);
});
return store;
}

Resources