auth0 / express-openid-connect

An Express.js middleware to protect OpenID Connect web applications.
MIT License
460 stars 139 forks source link

Be able to have different strategies of session storage between logged users or anonymous ones #623

Open Will956 opened 1 month ago

Will956 commented 1 month ago

Checklist

Describe the problem you'd like to have solved

We use this library to handle our sessions and store them in Redis. The drawback of that is those anonymous requests persist anonymous sessions in our Redis, and that can be huge (crawlers, scrapper, data scripts, etc...). We still want to persist those sessions somewhere because we attribute a session id for them. Our Redis cluster is so full of anonymous session and we have memory issues.

Describe the ideal solution

I guess the ideal solution will be to have different storage strategies based on logged-in or anonymous users.

Alternatives and current workarounds

At the moment, we init different instances of this library based on cookie value: if we know that we have a cookie of a logged-in user, we init the auth middleware that has Redis configuration (so logged-in sessions are persisted within Redis). If we know that we have a cookie of anonymous users, we init the auth middleware that persists sessions within the cookie.

Additional context

Our workaround works, but it seems hacky and the logic to know if it's a cookie from a logged-in user or not is not fully bullet-proof.

Maybe I'm missing something here and there is an obvious way of achieving that without this complexity.

Thanks!

madaster97 commented 1 month ago

@Will956 , I just tested a recent version of this SDK and did not see any anonymous sessions hit my custom session store.

If you clone this repo and do the following you should be able to replicate it:

  1. npm install (need dev dependencies)
  2. create a .env file and put DEBUG=memorystore in it
  3. run npm run start:example -- custom-session-store

You should see the following two lines when you first startup the app + begin a login (at localhost:3000):

  memorystore Init MemoryStore +0ms
  memorystore starting periodic check for expired sessions +0ms

And then you shouldn't see any other memorystore logs until after the login is complete, like this:

  memorystore SET "8bcc14114720cc4b83a1c545a3f938de" {"header":{"iat":1721500922,"uat":1721500922,"exp":1721587322},"data":{"id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xIn0.eyJzdWIiOiJhZGFtIiwibm9uY2UiOiJ2U25DUTJYUU00N3dSM0dOd1lnaDJ6UTFvdk14NGRwWWFkb1Q1b1gtNEVjIiwic19oYXNoIjoiQmRVRVctUTNVOEZaYkpxTzZlRzFGQSIsImF1ZCI6InRlc3QtZXhwcmVzcy1vcGVuaWQtY29ubmVjdC1jbGllbnQtaWQiLCJleHAiOjE3MjE1MDQ1MjAsImlhdCI6MTcyMTUwMDkyMCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDozMDAxIn0.iZs0VKD6hQXjZc0_9TiWU33M7Xm4MzBvs5YH2ZZqnH2QBZeDazs2N10Cw8RN4wJlKdUMet1xCjcLgonid2teN9LZBQ2JX3EiKHK_t8im4hYmDLW9jR3QVOo21bVTQQ2QPgxZwUuH60IAs34QtvEzJByapKpmkm6jp9Hf-fVQ1oo-DCaUtEOON6J9pgWVcjNsYKbEQVUjs-fboLoNA0DhR-T9xGfNtC0LPPngDYXK4z5FT2kLD8_e-iZD5tYeGK8w5ccKCpJGsFc0ZF6icOuPTtRpUWA0pOwctPbBuEgwZpd_x-4HpUuy2WtSGMiKOImMHm1V2gKtEqBvV4rrH3k_Bg","state":"eyJyZXR1cm5UbyI6Ii8ifQ"},"cookie":{"expires":1721587322000,"maxAge":86399051}} ttl:86399051 +22s
  memorystore GET "8bcc14114720cc4b83a1c545a3f938de" +10ms

The auth verification response cookies this SDK creates for anonymous sessions doesn't hit the custom store, they are always stateless sessions signed with the SECRET environment variable this SDK requires that you set: image

PS - I tested this in the context of other workflows like calling req.oidc.isAuthenticated(). Even using that function before login doesn't trigger calls to the session store.

Will956 commented 1 month ago

Hello @madaster97, thanks for looking!

There is something that I forgot to mention and, I think, it's important: we persist a session ID in the session object for anonymous sessions.

EDIT: that's what I said here, sorry maybe it was not clear

We still want to persist those sessions somewhere because we attribute a session id for them.

That's what's triggering the storage of that anonymous session I guess 😅

Did you try adding something to the anonymous session?

madaster97 commented 1 month ago

Ah yep I see what you mean. I see the same behavior if I try to set a req.appSession value before login. Not sure how difficult it would be to accommodate what you're asking for.

One word of warning, how are you using your session ID? Is it for CSRF protection/something similar? If that's the case, you probably want to toss that out on login anyway, so that you don't get some sort of session fixation vulnerability. General idea is someone could walk up to a computer and start a session/get the ID, and if someone else comes and logs in then the initial person would know their session ID.

If it was specifically CSRF you had in mind, you should check out a rejected PR 453 of mine discussing CSRF in this library. TLDR - the library's cookie attributes are generally good enough for CSRF protection (as long as you don't do stateful GETs).

Will956 commented 2 weeks ago

how are you using your session ID?

Mainly to link previous anonymised actions from an anonymous user to his analytics profile when he logs in. And yes we create a new one when the user logs in to prevent what you described!

Yes, that's quite a custom approach that this library may not want to cover. I'll let that open for a couple of days and will close if no one jumps on it.

Thanks for your input!