Standalone alternative to express-session for use in serverless context (w/ DynamoDB)

Viewed 107

Background: why use cookies with Lambdas?

OWASP is very clear that cookies are the best option for session management:

.. cookies .. are one of the most extensively used session ID exchange mechanisms, offering advanced capabilities not available in other methods.

However AWS's API Gateway literature often talks about using JWTs for authentication rather than cookies. While some tech blogs out there seem to think it's ok to use JWTs in this way, there are definitely recognised issues with JWTs. Two issues of particaular note are:

  • (a) you can't easily invalidate a JWT. At best you can keep a server-side database of blocked JWTs and make sure any service validating JWTs also implements a check against this block list. That sounds a lot like implementing regular old sessions, largely defeating the point of using JWTs.

  • (b) if your want to use JWTs for authorization as well as authentication, you'll run into issues when you need to update the authorization and it's not a change being driven by the enduser themselves. Scenarios in this category include: a system administrator or account manager changes the user's access level; a trial/contract is ended by a cron job; a webhook is triggered by a 3rd party SaaS integration (e.g. Stripe). You might say, "in that case use a separate mechanism for authorization", but then again you're back to good old sessions.

To be clear, I understand the value of JWTs in letting one server communicate its trust in a user's identity to another server, but that's a very different purpose to session management.

Session management in Node

All roads seem to lead to express-session as the most battle-tested implementation of sessions in Node. It offers a wide range of storage options to choose from*.

In the context of Lambdas, in principle you could try and use express-session as though it were just a function factory, for functions with the signature (req,res,next)=>void, that's rather hacky, and in no way recommended by express-sessions. It's also not entirely clear how best to match that call signature to the objects you get in an AWS Lambda, nor which storage mechanisms are optimised for lambdas (which are ephemeral and need to start quickly).

I would really like a lightweight node module that lets you do something like the following:

import {Sessions} from 'sessions';

// configure session management. Should be super lightweight for use in Lambda.
const sessions = new Sessions({
   /* ..basic cookie & expiration config, */
   secret: "something", // extra security recommended by express
   store: { // object with following interface:
      createSession(sessionId, metadata),
      getFromSessionId(sessionId),
      updateSession(sessionId, metadata),
      customIndexedProperties: ['userId'], // in addition to sessionId
      getSessionIdsFromIndexedProperty(propertyName, propertyValue),
   }
});

// create session. Note the api is not opinionated about response header mechanics.
response.headers['set-cookie'] = await sessions.createCookieForSession({
    userId: 'user1', 
    /*...other user info */
});

// get user's session. Again not opinionated about where cookie comes from.
const userSessionInfo = await sessions.getSessionFromCookie(request.header['cookies']);

// update a user's session, but not initiated by the user themselves
const sessionIds = await sessions.getSessionIdsFromIndexedProperty('userId', 'user1');
await sessions.updateSession(sessionIds[0], {something: 'has change'});

Questions

  1. Is my above thinking reasonable?
  2. Are there any node packages I've not encountered that might be helpful.
  3. If not, why not? I have come across a few people with closely related problems, but it must be a fairly common issue when working with serverless.
  4. If I were to implement a module to my own liking how do I get any confidence that I've done a good job security-wise? I could use pieces of express-session that are relevant, but that's not a great long-term solution for good security.
  5. Related to 4, if I were to try and hook into express-sessions, but just build my own store that does what I need, how would I get confidence in the security? Also, I haven't managed to find any docs on what the official api is for an express-session store, which I find amazing given that express-sessions seems to be the go to for sessions in Node.

Any help would be massively appreciated, thanks!

P.S. I appreciate a lot of what I'm discussing relates to open source projects that are often poorly funded. However, I was very surprised to have reached the above conclusions about the state of the ecosystem and wondered if I was missing something.


*Annoyingly, the suggested DynamoDb store package isn't great. Two of the features we'd want from it are not support, indeed PRs seem to have been opened back in 2019 but never looked at by the maintainer. Technically we don't absolutely have to use DynamoDb as our store, but it is does offer a lot of features we like.

0 Answers
Related