Skip to content
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

touch does not update session.cookie.expires #351

Open
thernstig opened this issue Feb 3, 2020 · 34 comments
Open

touch does not update session.cookie.expires #351

thernstig opened this issue Feb 3, 2020 · 34 comments
Assignees
Labels
Milestone

Comments

@thernstig
Copy link

thernstig commented Feb 3, 2020

When resave: false and rolling: true then the store will update the top-level expires in the session database on each request. express-session will also update the cookie and send it with every response.

The problem is that the stored document at the path session.cookie.expires does not get updated, so it is out-of-sync with both the top level expires as well as the expires in the cookie.

Since the touch() implementation already sends a call to the database to update the top-level expires should it not also update session.cookie.expires ?

This is the configuration of express-session:

  const store = new MongoStore({
    mongooseConnection: db,
    stringify: false,
  });

    session({
      secret: 'some_secret',
      resave: false,
      rolling: true,
      saveUninitialized: false,
      cookie: {
        maxAge: 60000,
        secure: true,
        httpOnly: true,
      },
      store,
    })

The actual document saved to the store looks something like this:

{
  "_id": "f2yQHE_BPi6UKV4pMuM7xluGPwQIhxIU",
  "expires": {
    "$date": "2020-02-03T15:23:54.646Z"
  },
  "session": {
    "cookie": {
      "originalMaxAge": 3599997,
      "expires": {
        "$date": "2020-02-03T15:04:06.890Z"
      },
      "secure": false,
      "httpOnly": true,
      "domain": null,
      "path": "/",
      "sameSite": null
    },
    "passport": {
      "user": "someUser"
    }
  }
}
@stale
Copy link

stale bot commented Apr 3, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 3, 2020
@thernstig
Copy link
Author

Activity!

@stale stale bot removed the wontfix label Apr 3, 2020
@stale
Copy link

stale bot commented Jun 2, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jun 2, 2020
@thernstig
Copy link
Author

Unstale

@stale stale bot removed the wontfix label Jun 2, 2020
@mingchuno
Copy link
Collaborator

So what is the expected behavior? The inner expires should sync with the outer one? If it is a bug. What is the current impact?

@stale
Copy link

stale bot commented Sep 18, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Sep 18, 2020
@thernstig
Copy link
Author

Unstale

@stale stale bot removed the wontfix label Sep 18, 2020
@stale
Copy link

stale bot commented Nov 19, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Nov 19, 2020
@thernstig
Copy link
Author

unstale

Ping @mingchuno

@stale stale bot removed the wontfix label Nov 19, 2020
@AaronPorts
Copy link

As cookie expiration may be taken from the session line, it may lead to bugs if these two lines won't be synchronized. I think adding updateFields.session = this.transformFunctions.serialize(session) should fix this.

connect-mongo/src/index.js

Lines 350 to 352 in 6c62235

if (session && session.cookie && session.cookie.expires) {
updateFields.expires = new Date(session.cookie.expires)
} else {

@stale
Copy link

stale bot commented Jan 20, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jan 20, 2021
@thernstig
Copy link
Author

unstale

@stale stale bot removed the wontfix label Jan 21, 2021
@thernstig
Copy link
Author

Ping @YC

@YC
Copy link
Contributor

YC commented Jan 22, 2021

connect-mongo/src/index.js

Lines 350 to 354 in 6c62235

if (session && session.cookie && session.cookie.expires) {
updateFields.expires = new Date(session.cookie.expires)
} else {
updateFields.expires = new Date(Date.now() + this.ttl * 1000)
}

test('test_session_touch', done => {
getNativeDbConnection(async (store, db, collection) => {
const sid = 'test_touch-sid'
const data = makeData()
await store.set(sid, data)
const session = await collection.findOne({ _id: sid })
assertSessionEquals(sid, data, session)
await store.touch(sid, session.session)

test('test_session_lazy_touch_sync', done => {
getNativeDbConnection({ touchAfter: 2 }, async (store, db, collection) => {
const sid = 'test_lazy_touch-sid-sync'
const data = makeData()
await store.set(sid, data)
const session = await collection.findOne({ _id: sid })
const lastModifiedBeforeTouch = session.lastModified.getTime()
await store.touch(sid, session)

The tests seem to be inconsistent as to what should be passed in the touch function.

@thernstig
Copy link
Author

@YC do you recon what I described in my original post is the correct thing?

@YC
Copy link
Contributor

YC commented Jan 22, 2021

If the cookie is updated due to rolling, I think it makes sense for session.cookie and its expiry to be updated accordingly also.
expressjs/session#33 (comment)

@thernstig
Copy link
Author

@YC great, looking forward to the fix :)

@mingchuno
Copy link
Collaborator

@thernstig @YC I have just rewrite the code using TS and published a new version! Can you please help me try it out to see of it fix your issue? https://www.npmjs.com/package/connect-mongo

@stale
Copy link

stale bot commented Jun 2, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jun 2, 2021
@thernstig
Copy link
Author

unstale

@stale stale bot removed the wontfix label Jun 2, 2021
@stale
Copy link

stale bot commented Aug 3, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Aug 3, 2021
@YC
Copy link
Contributor

YC commented Aug 3, 2021

unstale

@stale stale bot removed the wontfix label Aug 3, 2021
@mingchuno
Copy link
Collaborator

@YC What still need to be follow up on this issue?

@YC
Copy link
Contributor

YC commented Aug 3, 2021

Current Behavior

resave rolling expires session.expires
false false y n
false true y n
true false y y
true true y y

Expected Behavior (my opinion)

I performed a quick search on expires.
It seems like to me that it (the top level expires) is used to perform faster queries and should reflect the value in the cookie.

resave rolling expires session.expires Justification
false false n n If session is not modified and resave is false, then db should be unchanged.
false true y y "With [rolling] enabled, the session identifier cookie will expire in maxAge since the last response was sent instead of in maxAge since the session was last modified by the server." Expiration always rolling. (See discussion in issue linked above)
true false n n resave forces the session to be saved back to the session store. No mention of expires
true true y y "With [rolling] enabled, the session identifier cookie will expire in maxAge since the last response was sent instead of in maxAge since the session was last modified by the server."

Reference: https://expressjs.com/en/resources/middleware/session.html

Happy to have a look at code if everyone agrees.

@YC
Copy link
Contributor

YC commented Aug 7, 2021

Here are the logs from the different cases.

resave: true, rolling: true
2021-08-07T06:00:39.109Z connect-mongo create MongoStore instance
2021-08-07T06:00:39.113Z connect-mongo Creating MongoDB TTL index
Sat, 07 Aug 2021 06:00:39 GMT express-session no SID sent, generating session
Sat, 07 Aug 2021 06:00:39 GMT express-session saving DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
2021-08-07T06:00:39.119Z connect-mongo MongoStore#set=DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
Sat, 07 Aug 2021 06:00:39 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:39.119Z,
    originalMaxAge: 86400000,
    httpOnly: true
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:39 GMT express-session set-cookie connect.sid=s%3ADJW_JaSWR-41-zW3df0G0g7HB8t5bwK4.Mlxlz9E4Fec%2BzWdLz%2F1GwBnUpo9w1vQ2H2FDxz1GAOY; Path=/; Expires=Sun, 08 Aug 2021 06:00:39 GMT; HttpOnly
Sat, 07 Aug 2021 06:00:40 GMT express-session fetching DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
2021-08-07T06:00:40.629Z connect-mongo MongoStore#get=DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
Sat, 07 Aug 2021 06:00:40 GMT express-session session found
Sat, 07 Aug 2021 06:00:40 GMT express-session saving DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
2021-08-07T06:00:40.634Z connect-mongo MongoStore#set=DJW_JaSWR-41-zW3df0G0g7HB8t5bwK4
Sat, 07 Aug 2021 06:00:40 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:40.634Z,
    originalMaxAge: 86400000,
    httpOnly: true,
    secure: null,
    domain: null,
    sameSite: null
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:40 GMT express-session set-cookie connect.sid=s%3ADJW_JaSWR-41-zW3df0G0g7HB8t5bwK4.Mlxlz9E4Fec%2BzWdLz%2F1GwBnUpo9w1vQ2H2FDxz1GAOY; Path=/; Expires=Sun, 08 Aug 2021 06:00:40 GMT; HttpOnly
resave: false, rolling: true
2021-08-07T06:00:40.648Z connect-mongo create MongoStore instance
2021-08-07T06:00:40.655Z connect-mongo Creating MongoDB TTL index
Sat, 07 Aug 2021 06:00:40 GMT express-session no SID sent, generating session
Sat, 07 Aug 2021 06:00:40 GMT express-session saving tDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_
2021-08-07T06:00:40.662Z connect-mongo MongoStore#set=tDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_
Sat, 07 Aug 2021 06:00:40 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:40.662Z,
    originalMaxAge: 86400000,
    httpOnly: true
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:40 GMT express-session set-cookie connect.sid=s%3AtDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_.sQdrQCEzsT7%2Boc6LXJJZJEUCi%2BWLNQgEajuayXEVefQ; Path=/; Expires=Sun, 08 Aug 2021 06:00:40 GMT; HttpOnly
Sat, 07 Aug 2021 06:00:42 GMT express-session fetching tDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_
2021-08-07T06:00:42.173Z connect-mongo MongoStore#get=tDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_
Sat, 07 Aug 2021 06:00:42 GMT express-session session found
Sat, 07 Aug 2021 06:00:42 GMT express-session touching
2021-08-07T06:00:42.177Z connect-mongo MongoStore#touch=tDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:42.177Z,
    originalMaxAge: 86400000,
    httpOnly: true,
    secure: null,
    domain: null,
    sameSite: null
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:42 GMT express-session split response
Sat, 07 Aug 2021 06:00:42 GMT express-session set-cookie connect.sid=s%3AtDfmWIhYXIVhMQKU75xOA7EhrHIsFUM_.sQdrQCEzsT7%2Boc6LXJJZJEUCi%2BWLNQgEajuayXEVefQ; Path=/; Expires=Sun, 08 Aug 2021 06:00:42 GMT; HttpOnly
Sat, 07 Aug 2021 06:00:42 GMT express-session touched
resave: true, rolling: false
2021-08-07T06:00:42.209Z connect-mongo create MongoStore instance
2021-08-07T06:00:42.212Z connect-mongo Creating MongoDB TTL index
Sat, 07 Aug 2021 06:00:42 GMT express-session no SID sent, generating session
Sat, 07 Aug 2021 06:00:42 GMT express-session saving glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
2021-08-07T06:00:42.216Z connect-mongo MongoStore#set=glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
Sat, 07 Aug 2021 06:00:42 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:42.216Z,
    originalMaxAge: 86400000,
    httpOnly: true
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:42 GMT express-session set-cookie connect.sid=s%3AglO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW.n0ndWlNgUA4F5dQPto6h2wTHB7W2oG3rE0VUv%2BbZuj4; Path=/; Expires=Sun, 08 Aug 2021 06:00:42 GMT; HttpOnly
Sat, 07 Aug 2021 06:00:43 GMT express-session fetching glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
2021-08-07T06:00:43.725Z connect-mongo MongoStore#get=glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
Sat, 07 Aug 2021 06:00:43 GMT express-session session found
Sat, 07 Aug 2021 06:00:43 GMT express-session saving glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
2021-08-07T06:00:43.730Z connect-mongo MongoStore#set=glO8qxkC2gEkvf8IXsPR5Qtl0zL0rgyW
Sat, 07 Aug 2021 06:00:43 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:43.730Z,
    originalMaxAge: 86400000,
    httpOnly: true,
    secure: null,
    domain: null,
    sameSite: null
  },
  x: 0
}
resave: false, rolling: false
2021-08-07T06:00:43.746Z connect-mongo create MongoStore instance
2021-08-07T06:00:43.753Z connect-mongo Creating MongoDB TTL index
Sat, 07 Aug 2021 06:00:43 GMT express-session no SID sent, generating session
Sat, 07 Aug 2021 06:00:43 GMT express-session saving SEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5
2021-08-07T06:00:43.761Z connect-mongo MongoStore#set=SEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5
Sat, 07 Aug 2021 06:00:43 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:43.761Z,
    originalMaxAge: 86400000,
    httpOnly: true
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:43 GMT express-session set-cookie connect.sid=s%3ASEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5.cEF8QS9s9bj%2FsOX0w2TICNlGFHeUwQChBo0z4DBoXFI; Path=/; Expires=Sun, 08 Aug 2021 06:00:43 GMT; HttpOnly
Sat, 07 Aug 2021 06:00:45 GMT express-session fetching SEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5
2021-08-07T06:00:45.272Z connect-mongo MongoStore#get=SEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5
Sat, 07 Aug 2021 06:00:45 GMT express-session session found
Sat, 07 Aug 2021 06:00:45 GMT express-session touching
2021-08-07T06:00:45.277Z connect-mongo MongoStore#touch=SEBpItQ9cEs2qWWZVIgQbTpuWXieEzg5
Sat, 07 Aug 2021 06:00:45 GMT express-session split response
Session {
  cookie: {
    path: '/',
    _expires: 2021-08-08T06:00:45.276Z,
    originalMaxAge: 86400000,
    httpOnly: true,
    secure: null,
    domain: null,
    sameSite: null
  },
  x: 0
}
Sat, 07 Aug 2021 06:00:45 GMT express-session touched

rolling seems to trigger set-cookie, which follows from https://github.com/expressjs/session/blob/master/index.js#L472
resave: true causes set to be called, instead of touch.
However, I don't see a way to keep the db in sync. Any ideas?

@LouisVA
Copy link

LouisVA commented Feb 25, 2022

unstale.....

@stale
Copy link

stale bot commented Apr 28, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 28, 2022
@YC YC removed their assignment Apr 28, 2022
@stale stale bot removed the wontfix label Apr 28, 2022
@YC
Copy link
Contributor

YC commented Apr 28, 2022

Since it's not perhaps very clear how this mechanism works, it might be beneficial to write some integration tests against express-session.
Unassigning myself for now...

@sayhicoelho
Copy link

sayhicoelho commented Jun 17, 2023

Setting rolling: true fixed the issue, but still not updating session.cookie.expires in the database.

image

expires: 15:34:51
session.cookie.expires: 15:34:26 (outdated)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants