-
-
Notifications
You must be signed in to change notification settings - Fork 54
Remove session id and encrypted session id from session data #114
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
Changes from all commits
28f5c93
c07c6c5
69c0551
07ccc0d
6ea8222
732b089
ebb0a72
4d79c0a
ea68b95
b73c0ab
0dcc544
96c180c
5abe743
8efbe87
65712d2
517f6d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,36 +10,33 @@ const stringify = configureStringifier({ bigint: false }) | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const maxAge = Symbol('maxAge') | ||||||||||||||||||||||||||||||||
| const secretKey = Symbol('secretKey') | ||||||||||||||||||||||||||||||||
| const sign = Symbol('sign') | ||||||||||||||||||||||||||||||||
| const addDataToSession = Symbol('addDataToSession') | ||||||||||||||||||||||||||||||||
| const generateId = Symbol('generateId') | ||||||||||||||||||||||||||||||||
| const requestKey = Symbol('request') | ||||||||||||||||||||||||||||||||
| const cookieOptsKey = Symbol('cookieOpts') | ||||||||||||||||||||||||||||||||
| const originalHash = Symbol('originalHash') | ||||||||||||||||||||||||||||||||
| const hash = Symbol('hash') | ||||||||||||||||||||||||||||||||
| const sessionIdKey = Symbol('sessionId') | ||||||||||||||||||||||||||||||||
| const encryptedSessionIdKey = Symbol('encryptedSessionId') | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| module.exports = class Session { | ||||||||||||||||||||||||||||||||
| constructor (request, idGenerator, cookieOpts, secret, prevSession = {}) { | ||||||||||||||||||||||||||||||||
| constructor (request, idGenerator, cookieOpts, secret, prevSession = {}, sessionId = idGenerator(request)) { | ||||||||||||||||||||||||||||||||
| this[generateId] = idGenerator | ||||||||||||||||||||||||||||||||
| this.expires = null | ||||||||||||||||||||||||||||||||
| this.cookie = new Cookie(cookieOpts) | ||||||||||||||||||||||||||||||||
| this[cookieOptsKey] = cookieOpts | ||||||||||||||||||||||||||||||||
| this[maxAge] = cookieOpts.maxAge | ||||||||||||||||||||||||||||||||
| this[secretKey] = secret | ||||||||||||||||||||||||||||||||
| this[addDataToSession](prevSession) | ||||||||||||||||||||||||||||||||
| this[requestKey] = request | ||||||||||||||||||||||||||||||||
| this.touch() | ||||||||||||||||||||||||||||||||
| if (!this.sessionId) { | ||||||||||||||||||||||||||||||||
| this.sessionId = this[generateId](this[requestKey]) | ||||||||||||||||||||||||||||||||
| this.encryptedSessionId = this[sign]() | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| this[sessionIdKey] = sessionId | ||||||||||||||||||||||||||||||||
| this[encryptedSessionIdKey] = cookieSignature.sign(sessionId, secret) | ||||||||||||||||||||||||||||||||
| this[originalHash] = this[hash]() | ||||||||||||||||||||||||||||||||
| this.touch() // Needs to happen after originalHash is set, in case maxAge forces an update | ||||||||||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a bug in the original PR. Added a test against it
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! |
||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| touch () { | ||||||||||||||||||||||||||||||||
| if (this[maxAge]) { | ||||||||||||||||||||||||||||||||
| this.expires = new Date(Date.now() + this[maxAge]) | ||||||||||||||||||||||||||||||||
| this.cookie.expires = this.expires | ||||||||||||||||||||||||||||||||
| this.cookie.expires = new Date(Date.now() + this[maxAge]) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -71,7 +68,7 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| [addDataToSession] (prevSession) { | ||||||||||||||||||||||||||||||||
| for (const key in prevSession) { | ||||||||||||||||||||||||||||||||
| if (!['expires', 'cookie'].includes(key)) { | ||||||||||||||||||||||||||||||||
| if (!['cookie', 'sessionId', 'encryptedSessionId'].includes(key)) { | ||||||||||||||||||||||||||||||||
| this[key] = prevSession[key] | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
@@ -87,14 +84,14 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| destroy (callback) { | ||||||||||||||||||||||||||||||||
| if (callback) { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.destroy(this.sessionId, error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.destroy(this[sessionIdKey], error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = null | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| callback(error) | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.destroy(this.sessionId, error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.destroy(this[sessionIdKey], error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = null | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (error) { | ||||||||||||||||||||||||||||||||
|
|
@@ -109,15 +106,15 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| reload (callback) { | ||||||||||||||||||||||||||||||||
| if (callback) { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.get(this.sessionId, (error, session) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session) | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.get(this[sessionIdKey], (error, session) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session, this[sessionIdKey]) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| callback(error) | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.get(this.sessionId, (error, session) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session) | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.get(this[sessionIdKey], (error, session) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].session = new Session(this[requestKey], this[generateId], this[cookieOptsKey], this[secretKey], session, this[sessionIdKey]) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (error) { | ||||||||||||||||||||||||||||||||
| reject(error) | ||||||||||||||||||||||||||||||||
|
|
@@ -131,12 +128,12 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| save (callback) { | ||||||||||||||||||||||||||||||||
| if (callback) { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.set(this.sessionId, this, error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.set(this[sessionIdKey], this, error => { | ||||||||||||||||||||||||||||||||
| callback(error) | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.set(this.sessionId, this, error => { | ||||||||||||||||||||||||||||||||
| this[requestKey].sessionStore.set(this[sessionIdKey], this, error => { | ||||||||||||||||||||||||||||||||
| if (error) { | ||||||||||||||||||||||||||||||||
| reject(error) | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
|
|
@@ -147,16 +144,13 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| [sign] () { | ||||||||||||||||||||||||||||||||
| return cookieSignature.sign(this.sessionId, this[secretKey]) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| [hash] () { | ||||||||||||||||||||||||||||||||
| const sess = this | ||||||||||||||||||||||||||||||||
| const str = stringify(sess, function (key, val) { | ||||||||||||||||||||||||||||||||
| // ignore sess.cookie property | ||||||||||||||||||||||||||||||||
| if (this === sess && key === 'cookie') { | ||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||
| // we want `touch` to affect the hash of the session | ||||||||||||||||||||||||||||||||
| return sess.cookie.expires?.getTime() | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| return val | ||||||||||||||||||||||||||||||||
|
|
@@ -169,15 +163,28 @@ module.exports = class Session { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| isModified () { | ||||||||||||||||||||||||||||||||
| return this[originalHash] !== this[hash]() | ||||||||||||||||||||||||||||||||
| return Boolean( | ||||||||||||||||||||||||||||||||
| this[originalHash] !== this[hash]() || | ||||||||||||||||||||||||||||||||
| // If maxAge is set, the session is modified. | ||||||||||||||||||||||||||||||||
| // This is necessary because we don't read the cookie's expiration from the cookie itself. | ||||||||||||||||||||||||||||||||
| // session.cookie.expires is initially set from Cookie(cookieOpts), so we cannot detect if it changed from maxAge alone. | ||||||||||||||||||||||||||||||||
| this[maxAge] | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+166
to
+172
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
However, this seems wrong. Just setting a max age should never make
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We should probably do that, and isn't that what happens with your
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I wish! cookie.expires is set using maxAge upon initialization anyway: But you're right, Also, we probably want to eventually support session stores that implement the Reverting this but I'm not quite sure how to implement this otherwise... need to think about it
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah -- I'm mistaken. This code is confusing :) If |
||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| get sessionId () { | ||||||||||||||||||||||||||||||||
| return this[sessionIdKey] | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| get encryptedSessionId () { | ||||||||||||||||||||||||||||||||
| return this[encryptedSessionIdKey] | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| static restore (request, idGenerator, cookieOpts, secret, prevSession) { | ||||||||||||||||||||||||||||||||
| const restoredSession = new Session(request, idGenerator, cookieOpts, secret, prevSession) | ||||||||||||||||||||||||||||||||
| static restore (request, idGenerator, cookieOpts, secret, prevSession, sessionId) { | ||||||||||||||||||||||||||||||||
| const restoredSession = new Session(request, idGenerator, cookieOpts, secret, prevSession, sessionId) | ||||||||||||||||||||||||||||||||
| const restoredCookie = new Cookie(cookieOpts) | ||||||||||||||||||||||||||||||||
| restoredCookie.expires = new Date(prevSession.cookie.expires) | ||||||||||||||||||||||||||||||||
| restoredSession.cookie = restoredCookie | ||||||||||||||||||||||||||||||||
| restoredSession.expires = restoredCookie.expires | ||||||||||||||||||||||||||||||||
| restoredSession[originalHash] = restoredSession[hash]() | ||||||||||||||||||||||||||||||||
| return restoredSession | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should re-evaluate: