express-openid-connect and in-flight requests
you’ve written your front end piece. you need serve it somehow. ok. spin up a quick express
server. you want multiple people to use it. ugh. ok. get your auth0 account, go through their setup flow, everything looks good. except…
for some reason when you try to log the user out, they get logged back in immediately. why do bad things happen to good people. ok. they click the button. it window.location.assign('/logout')
s. that looks good. pop open the dev console (jk you already have it open because it’s always open). window.location.assign('/logout')
. that works, and doesn’t log the user back in. hmm. you pop open the network tab and take a look:
hmmm…
session data is usually stored in the cookies, so you’d bet that the cookie just isn’t getting cleared. you peek at the request cookies in the /
request:
as you suspected, that looks like a valid appSession
cookie (which is what express-openid-connect
uses to store the active login). clearly the library is failing to clear the cookie. triumphantly, you take a look at the /logout
request:
wait - it is clearing the session. the response cookies appSession
has a value: ""
which should definitely clear it. how is it reset right before login…?
looking back at the network calls you click on the only possible culprit: the /update
call that you make to record the “user clicked logout button” action. and sure enough:
ok. so you get the picture now. when the user clicks the “logout” button the front end both fires off an async /update
request to the server, and redirects the window to /logout
. /logout
comes back first and clears the session, but the response to /update
comes back /after/ and /resets/ the cookie that was just cleared.
but why does express-openid-connect
set the user’s login cookie (appSession
) in the response to /update
? that’s a route you created, and has nothing to do with logging in or out.
turns out, it’s because the library uses a rolling session so that every request made from the client to the server extends the user’s current session. makes sense you guess, but you’re not sure that something like /update
/should/ extend the user’s session (for example, what if you’re updating about a period of inactivity?). philosophical problems aside, it’s breaking your logout flow.
the suggested solutions are
- use a custom session store
but this sounds like a lot of effort
- manage the concurrency application side
which is also a lot of effort given that now you’re dealing with concurrency. is there a dumb and easy way to do this?
after some thinking you realize there is. triumphantly opening up server.ts
you simply move the /update
handler to /before/ the call to app.use(auth(authConfig))
. express
only applies handlers to routes that are defined /after/ the handler is use
d, so that means the auth
handler doesn’t end up getting applied to this route. which means it doesn’t try to refresh the session, meaning the /update
response comes back without the appSession
cookie, which means the user doesn’t get logged back in!
it’s not pretty, but that’s perhaps a problem for another day.
(or perhaps you have a better idea? leave a comment! I’d love to know 😊)