Skip to content

Expire cookie immediately upon destroying session #242

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

JamesMGreene
Copy link
Contributor

Force an existing session's cookie to expire immediately upon destroying the session.

Fixes #241.

@JamesMGreene
Copy link
Contributor Author

@dougwilson: I'm sure you're day-job-and-open-source-swamped like the rest of us but if there is any chance of getting PR #240 and this PR merged and released within the next 2 weeks or so, my team and I would appreciate it! 👍 💝

@dougwilson
Copy link
Contributor

Hi James, sorry I haven't been on a computer since you made this. I will look at this pull request as soon as I can. I cannot comment on when this pull request would be accepted, because I need to understand first what the pull requests does and understand if this is a desired feature, if there are edges cases, etc.

I know you feel like it is a bug, but I need to look at it more, as to me, if feels like either a bug or a new feature.

@JamesMGreene
Copy link
Contributor Author

Sounds good, @dougwilson. Thanks! 👍

If you do end up feeling it is a new feature and would rather implement it as an option rather than as the new default behavior, I'd be fine with refactoring it to work as such if you give me a bit of design suggestion/guidance on how you'd like it to work.

I'll keep an eye out for any feedback requiring changes on my part. 👀

@JamesMGreene
Copy link
Contributor Author

@dougwilson: As mentioned in the issue (#241):

Perhaps this should only be the expected behavior if the cookie would've been updated normally anyway, e.g. if the rolling: true option was enabled.

@JamesMGreene
Copy link
Contributor Author

@dougwilson: If there is any chance of this being merged and released before Monday, I'd 💛 you for it.

@dougwilson
Copy link
Contributor

Hi @JamesMGreene , I'm sorry, I really wanted to (even did a few commits to this repo tonight, yay!) get this done tonight, before Monday for you. I just didn't get to, but what I did do is at least published the changes to npm that we had so far, and then I really want to get this change done on Monday for you.

@JamesMGreene
Copy link
Contributor Author

@dougwilson: If it makes it in this week, I can probably still pull it into our release branch. Monday would be best if possible so I can just get it into the mainline branch, though. 👍

@dougwilson
Copy link
Contributor

Yea, I'm working on it. Just looked at it and there are all kinds of nits, like the function in index.js is not alphabetically sorted like the rest, the tests are in the wrong location/their descriptions are too long. I'm working on adjusting.

@dougwilson
Copy link
Contributor

And a reassignment of an argument, which results in a v8 de-opt.

@dougwilson
Copy link
Contributor

Hi! It seems like if a user calls req.session.destroy() in their code, then it won't actually set the expired cookie. This seems very unexpected and one would expect that the method of destruction would not change if the cookie is expired or not. Example test app:

var app = express()
.use(session({ secret: 'keyboard cat', cookie: { maxAge: 86400000 } }))
.use(function(req, res, next){
  req.session.count = req.session.count || 0;
  req.session.count++;
  if (req.session.count === 2) {
    req.session.destroy(function(err) {
      if (err) return next(err);
      res.end();
    });
  } else {
    res.end();
  }
});

index.js Outdated
* @return {Cookie}
* @private
*/
function createCookie(cookieOptions, req, trustProxy) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this to be alphabetical within all these functions while you're working on the destroy issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@dougwilson
Copy link
Contributor

Hi @JamesMGreene , I'm not in a rush, but I know you seemed to be, so I just wanted to put a note here just in case you missed my comment in #242 (comment)

@JamesMGreene
Copy link
Contributor Author

Thanks, @dougwilson. You caught me in the thralls of our busy release sprint, so I didn't have any time to address this.

I should be able to take a look this week. I'm OK with this change not going out with our next release; my PR #240 being merged into v1.13.0 was the more important change. 👍

@JamesMGreene
Copy link
Contributor Author

the tests are in the wrong location/their descriptions are too long

@dougwilson: Can you fill me in more on this comment?

@JamesMGreene
Copy link
Contributor Author

It seems like if a user calls req.session.destroy() in their code, then it won't actually set the expired cookie. This seems very unexpected and one would expect that the method of destruction would not change if the cookie is expired or not.

Working through this issue now.

@JamesMGreene
Copy link
Contributor Author

JamesMGreene commented Jun 14, 2016

Alright, so the problem with when the user calls req.session.destroy() — without also setting the unset: "destroy" option — is that shouldDestroy(req) returns false, ergo the isBeingDestroyed variable is also set to false:

// Is this an existing session that is being destroyed?
var isBeingDestroyed = !!cookieId && shouldDestroy(req);

Reminder of current shouldDestroy implementation:

// determine if session should be destroyed
function shouldDestroy(req) {
  return req.sessionID && unsetDestroy && req.session == null;
}

@dougwilson et al: Any advice on how to workaround this situation?


P.S. Note that if you do set the unset: "destroy" option, then it works as expected.

@dougwilson
Copy link
Contributor

Hi @JamesMGreene, sorry I didn't reply right away; I was just trying to focus on pushing out Express 4.14 :) So I think that that is probably just not a full understanding of the current code, that that's OK! At least how it is designed right now, the shouldDestroy and similar is only there to track if the "auto saving" part of this module should basically destroy it instead of save it. This functionality is completely independent of tracking if the session has been manually destroyed or not. You probably have to add manual tracking for this, similar to how we manually track if a session has manually been saved or not.

@JamesMGreene
Copy link
Contributor Author

OK, gotcha @dougwilson. I'll look into that further.

@JamesMGreene
Copy link
Contributor Author

@dougwilson: Finally found a bit of time to dig into this further and get it all working. Please re-review the new version when you get a chance. Thanks!

@dougwilson
Copy link
Contributor

Hi @JamesMGreene , it looks like the last commit was Dec 10, 2015. Is that the most recent version?

@JamesMGreene
Copy link
Contributor Author

@dougwilson: No, sorry, that was because I did a git commit --amend (so it maintained the old commit's date). I've pushed a new replacement commit now dated as today for better accuracy.

@JamesMGreene
Copy link
Contributor Author

gently pokes @dougwilson No rush but a gentle reminder. :)

@bsodmike
Copy link

@JamesMGreene You'll need to clean up re. the conflict 👍

@JamesMGreene
Copy link
Contributor Author

Rebased and dealt with merge conflicts again. 👍

@@ -396,6 +410,16 @@ function session(options) {
});
}

// check if session has been or is being destroyed
function isBeingDestroyed(req) {
return req.sessionID && req.session == null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check that unsetDestroy is true here? That option is what makes the unsetting of req.session actually mean the session is to be destroyed, otherwise it does nothing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, if I add that check here, the tests don't pass any longer, but if I don't add the check, then req.session = null will destroy the cookie even if the user doesn't want req.session = null to destroy the session...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, sounds like I must need another unit test for that last condition you mentioned. I'll take a peek when I get a chance.

@@ -1269,14 +1532,14 @@ describe('session()', function(){
.get('/')
.expect(shouldNotHaveHeader('Set-Cookie'))
.expect(200, function(err, res){
if (err) return done(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a bunch of accidental changes here with the formatting; I can fix, but figured I'd comment here in case you had to make a change from the question above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that doesn't surprise me too much as it seemed like someone changed the test code style (e.g. to be semi-colon-less) in the time since my initial PR submission. I'll try to clean them up when I make my updates.

assert.ok(delta <= 0)

delta = b.valueOf() - now.valueOf()
assert.ok(delta <= 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a shouldSetCookieToExpireIn helper that could probably be used here if you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for letting me know. I'll take a peek and see if/where it makes sense to use.

@dougwilson
Copy link
Contributor

Hi @JamesMGreene , I know it has been a long time. I let these PRs just sit and I'm trying to make it right by getting them all merged in. I went and rebased all your changes, and even made the adjustments I noted above. It doesn't seem like I'm able to push to your fork, though.

If you haven't already done so, checking off the allow on the right hand side (https://help.github.com/en/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork) would allow me to push up the changes + rebase and then merge the pull request.

But this is not a requirement to land your changes, it just will make the PR show as "merged" instead of "closed". If you're no longer around to do so / don't want to / whatever, it's no big deal. I will plan to merge it within a couple weeks if I don't hear back.

@dougwilson dougwilson force-pushed the master branch 2 times, most recently from 9d2e29b to 408229e Compare January 28, 2024 20:24
@bjohansebas bjohansebas modified the milestone: 2.0.0 Feb 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cookie should expire immediately when session is destroyed
7 participants