NodeJS - How to disable the Session for a specific route - node.js

I would like to disable the session creation for a specific route, as "/app/....";
I tried one way by using the code see below :
pool = mysql.createPool(mysqlOptions);
var sessionConnection = mysql.createConnection(mysqlOptions);
var sessionStore = new MySQLStore(mysqlOptions, sessionConnection);
app.use(function(req, res, next){
if (!req.path.startsWith("/app/"))
session({
key: 'x',
secret: 'x',
store: sessionStore,
resave: false,
saveUninitialized: true,
cookie: {maxAge: moment().endOf('days').diff(moment())} })(req, res, next);
else
next();
});
I have the warning message see bellow and after few minutes, the server is not reachable.
MaxListenersExceededWarning: Possible EventEmitter memory leak
detected. 11 disconnect listeners added to [MySQLStore]. Use
emitter.setMaxListeners() to increase limit
Could somebody explain me ? Thanks in advance.

If you put the route declaration BEFORE your session middleware, then the session will not be created for that specific route handler.
app.use("/app", appRouter); // this will be handled before session is created
app.use(session(...));
If you want to call the session dynamically the way you are in your code, then you should create the session middleware once and then call that dynamically:
pool = mysql.createPool(mysqlOptions);
const sessionConnection = mysql.createConnection(mysqlOptions);
const sessionStore = new MySQLStore(mysqlOptions, sessionConnection);
const sessionMiddleware = session({
key: 'x',
secret: 'x',
store: sessionStore,
resave: false,
saveUninitialized: true,
cookie: {maxAge: moment().endOf('days').diff(moment())}
});
app.use(function(req, res, next){
if (!req.path.startsWith("/app/"))
sessionMiddleware(req, res, next);
else
next();
});

Related

Res header contaisn set Cookie but browser isn't storing it

I'm using express-session to store session cookie. I can see Set-Cookie connect.ssid under the response header but for some reason it is not getting stored in the cookie.
I'm wondering if this is a CORS issue, my app file looks like this. Should I change something here to make it work.
const session = require('express-session');
const config = require('config');
var MemoryStore = require('memorystore')(session);
module.exports = function (app) {
// app.use(
// session({
// secret: 'key sign',
// resave: false,
// saveUninitialized: false
// })
// );
app.use(express.json());
app.use(cors({ credentials: true }));
enter code here
app.set('trust proxy', 1);
app.use(
session({
saveUninitialized: false,
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000
}),
resave: false,
cookie: { secure: false },
secret: config.get('sessionStorage')
})
);
app.use('/api/users', users);
Here is how I fixed this.
Add SSL to both frontend and backend.
If it is self-signed, ensure browser trust it. For example, if you're using mac, go to keychain, select specific certificate and select always trust option.
Restart the system. Only then SSL will be properly set otherwise there would still be insecure badge in the navigations.

How can I get the current session information from express-session?

I am using express-session to store my session data for my Node app as follows:
import express from 'express';
import session from 'express-session';
import connectRedis from 'connect-redis';
const app = express();
const RedisStore = connectRedis(session);
app.use(session({
secret: 'keyboard kat',
store: new RedisStore({
url: '//redis:6379',
}),
resave: false,
saveUninitialized: false,
proxy: true,
cookie: {
secure: true,
},
}));
and I'm trying to get the information of the current session in the browser. I tried typing session in the console to no avail. Similarly, adding a console.log(session) below where I set up use of the session in the app doesn't work. How can I get the current session information from express-session?
You can simply use your app with a function that references the session
app.use(function (req, res, next) {
console.log(req.session)
})
but it will print to the command line running your Node server rather than the console of the browser.

Express Set Session for Specific Routes

I am trying to include sessions only for some routes (the authentication ones) but I am having a problem because of the error page routes:
I have this:
app.use(session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
}));
app.use('/api/user', require('./api/user'));
app.use('/api/auth', require('./api/auth'));
app.route(['/error/500','/error/404','/user/settings'])
.get((req, res) => {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
app.route('/*/*')
.get(errors[404]);
app.use(errors[500]);
So, If I use it like this, all the pages in my application will create a session (which I don't want). If I move the session section after the error routes, I will never get to the api routes because it will reach the 404 route.
Thanks in advance
Middleware can be associated with only certain routes and the order in which it is specified matters. There are a number of ways to do that and how to best implement it depends upon the paths your site uses and how you can most easily create a link between path and whether it should or should not have the session middleware on it.
One simple thing to do would be to put your error route handlers BEFORE your session middleware. Then, those route handlers would "handle" the request first and the session middleware would never get called.
app.route(['/error/500','/error/404','/user/settings'])
.get((req, res) => {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
app.use(session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
}));
Other things you can do:
Put a path on your session middleware so it is only invoked for certain paths in your site (all authenticated pages should be below that path).
Create your own middleware handler that checks to see if the path is /error and if not, then it invokes the session middleware handler. If it is /error, then don't invoke the session middleware.
This last one could be done like this:
const sessionHandler = session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
});
app.use(function(req, res, next) {
// if path does not start with /error/, then invoke session middleware
if (req.url.indexOf("/error/") !== 0) {
return sessionHandler(req, res, next);
} else {
next();
}
});
You can also chain/compose multiple middleware using Express.router() as mentioned in this example: Express: composing middleware
And then apply that composed router (of chained middleware) as a specific route handler.

Node.js session login

Node.js does not seem to be remembering my session.
I am using Express with cookie-parser and express-session as middleware.
In my application, I use Mongo to keep usernames and passwords.
The following is a MWE:
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var app = express();
app.use(cookieParser({
secret: 'derma-aid'
}));
app.use(session({
secret: 'derma-aid',
resave: false,
saveUninitialized: false,
cookie: {secure: false}
}));
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/login', function(req, res)
{
console.log('login');
req.session.user_id = 500;
res.send('<h1>login</h1>');
});
app.get('/view', function(req, res)
{
console.log('view id: ' + req.session.user_id);
res.send('<h1>view: ' + req.session.user_id + '</h1>');
});
app.get('/logout', function(req, res)
{
console.log('logout: ' + req.session.user_id);
res.send('<h1>logout: ' + req.session.user_id + '</h1>');
delete req.session.user_id;
});
app.listen(5000);
If you go to the browser to http://localhost:5000/login, then req.session.user_id should be set and displayed correctly on http://localhost:5000/view.
But, instead, I am getting undefined messages...
EDIT: cookie: {secure: false} as suggested by #tiblu. I get this error: TypeError: Secret string must be provided..
I managed to fix the TypeError: Secret string must be provided.
- app.use(cookieParser({
- secret: 'derma-aid'
- }));
+ app.use(cookieParser(
+ 'derma-aid'
+ ));
In your session middleware setup change from:
cookie: {secure: true}
to
cookie: {secure: false}
Cookies marked as secure are not sent for NON-HTTPS requests. You are accessing your application over HTTP.
More reading on that https://en.wikipedia.org/wiki/HTTP_cookie#Secure_cookie

How can I use Node.js Express-session inside a conditional middleware?

var express = require('express')
var parseurl = require('parseurl')
var session = require('express-session')
var app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
This is my simple code. However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?
I've tried:
function setSession(req,res,next){
if(req.url.indexOf('/api') != 0){
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
next();
}else{
next();
}
};
and then
app.use(setSession);
But setting req.session.hello = "world" in my controller gives: TypeError: Cannot set property 'hello' of undefined. Simply put, it doesn't work. Are my arguments wrong in my middleware?
However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?
You certainly can. You can use express.Router to create sub-routes, like this:
var sessionMiddleware = session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
});
var webRoutes = express.Router()
.get('/', function(req, res, next) {
res.send('I have a session!');
});
var nonWebRoutes = express.Router()
.get('/', function(req, res, next) {
res.send('No session here');
});
app.use('/web', express.Router()
.use(sessionMiddleware)
.use(webRoutes));
app.use('/nonweb', nonWebRoutes);
Edit:
If however you want to conditionally execute the middleware function, you could do it like this:
app.use(function(req, res, next) {
if (req.url.indexOf('/api') !== 0) {
sessionMiddleware(req, res, next);
} else {
next();
}
});
app.get('/api', function(req, res, next) {
res.send(!!req.session); //false
});
app.get('/web', function(req, res, next) {
res.send(!!req.session); //true
});
But I prefer the sub-route approach because it maps your path route structure to a hierarchy which makes the code easier to read and easier to incorporate other middleware that make use of sessions, like passport.js for example.

Resources