Prevent Expressjs from creating a session when requests contain an authorization header?

I have an API that can be called either through a browser, where the requests are transactional, or directly connected to the session, for example. using curl where the queries are atomic. Browser requests must first authenticate and then use an express session (connect.sid) for subsequent authorization, direct API calls use the header: Authorization: "SOMETOKEN" , which must be sent for each request.

The problem is that since I use the same web server to serve both atomic and transactional traffic, every API call gets an Express session uselessly. Each response includes a Set-Cookie, and all of these sessions populate my session store. Therefore: how can I prevent Express from entering a new sess key in the storage (Redis) when the request contains an authorization header?

Note. I understand that a more classic approach would be to have a separate API server and a separate WEB server, but why not run them on the same machine? For me, the difference is that the API serves the data, and the WEB serves the views, but in addition, they are part of the same application. It’s just that I’ll also allow users to directly access their data and not force them to use my interface.

Express configuration

 module.exports = function(app, exp, sessionStore, cookieParser, passport, flash) { app.configure(function(){ // Templates app.set('views', ERNEST.root + '/server/views'); app.set('view engine', 'jade'); app.set('view options', { doctype : 'html', pretty : true }); // Allow large files to be uploaded (default limit is 100mb) app.use(exp.limit('1000mb')); // Faux putting and deleting app.use(exp.methodOverride()); // Static content app.use(exp.static(ERNEST.root + '/server')); app.use(exp.static(ERNEST.root + '/public')); // Handle favicon app.use(exp.favicon()); // For uploads app.use(exp.bodyParser({keepExtensions: true})); // Configure cookie parsing if ( cookieParser ) app.use(cookieParser); else app.use(exp.cookieParser()); // Where to store the session var session_options = { 'secret': "and she put them on the mantlepiece" }; if ( sessionStore ) session_options.store = sessionStore; app.use(exp.session( session_options )); // Rememberance app.use( function (req, res, next) { if ( req.method == 'POST' && req.url == '/authenticate' ) { if ( req.body.rememberme === 'on' ) { req.session.cookie.maxAge = 2592000000; // 30*24*60*60*1000 Rememeber 'me' for 30 days } else { req.session.cookie.expires = false; } } next(); }); // PassportJS if ( passport ){ app.use(flash()); app.use(passport.initialize()); app.use(passport.session()); } }); }; 

Route Example

 app.get('/status/past_week', MID.ensureAuthenticated, MID.markStart, function(req, res) { WEB.getStatus('week', function(err, statuses){ if ( err ) res.send(500, err); else res.send(200, statuses); }); }); 

Middleware Authorization

 MID.ensureAuthenticated = function(req, res, next) { if ( req.isAuthenticated() ) return next(); else { isAuthorised(req, function(err, authorised){ if ( err ) return res.redirect('/'); else if ( authorised ) return next(); else return res.redirect('/'); }); } function isAuthorised(req, callback){ var authHeader = req.headers.authorization; if ( authHeader ) { // Has header, verify it var unencoded = new Buffer(authHeader, 'base64').toString(); var formatted = unencoded.toString().trim(); ACCOUNT.verifyAuth(formatted, callback); // verifyAuth callbacks next() when successful } else callback(null, false); // No Authorised header } }; 
+8
express connect
source share
4 answers

Try the following:

 var sessionMiddleware = exp.session( session_options ); app.use(function(req, res, next) { if (req.headers.authorization) { return next(); } return sessionMiddleware(req, res, next); }); 
+14
source share

It sounds like you need to write your own session middleware. Here is an example . If you can create a separate subdomain, say, www.example.com for browser sessions and app.example.com for direct access to it, then you should be able to use the associated method almost precisely and simply not to start a session for app.example requests. com. This may be the most direct method in which a call indicates the method that it intends to authenticate, and any deviation from it is an error.

Otherwise, you will have to detect the authentication token in the middleware and not start the session when you find it.

+1
source share

An alternative approach to reducing the number of sessions stored in the session store is to set maxAge to something low by default. Then, when you really need longer sessions, for example, after a user logs in, you can set req.session.cookie.expires = null; . Also, don't forget to set the session end time to something low when the user logs out.

Here is an example:

 // set default to something low app.use(session({ resave: true, saveUninitialized: true, cookie: { maxAge: 5 * 60 * 1000 // 5 minutes }, secret: secrets.sessionSecret, store: new MongoStore({ url: yourUrl, auto_reconnect: true }) })); // on successful login, // set expiration to null or something longer than default var time = 14 * 24 * 3600000; //2 weeks req.session.cookie.maxAge = time; req.session.cookie.expires = new Date(Date.now() + time); req.session.touch(); // on logout, reset expiration to something low var time = 5 * 60 * 1000; // 5 minutes req.session.cookie.maxAge = time; //2 weeks req.session.cookie.expires = new Date(Date.now() + time); req.session.touch(); 

This is especially useful when monitoring your application remotely, because if monitoring is frequent enough, sessions will quickly fill up.

+1
source share

You can always just catch the response header event and remove the 'set-cookie' header:

 app.use(function(req, res, next) { res.on('header', function () { if (req.headers.authorization) { delete res._headers['set-cookie']; } }); next(); }); 

You can technically put this in any middleware chain.

-one
source share

All Articles