Skip to content

Commit 0616699

Browse files
committed
Expire cookie immediately upon destroying session
Fixes #241.
1 parent 3a7e3d2 commit 0616699

File tree

2 files changed

+436
-25
lines changed

2 files changed

+436
-25
lines changed

Diff for: index.js

+59-16
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,7 @@ function session(options) {
157157
store.generate = function(req){
158158
req.sessionID = generateId(req);
159159
req.session = new Session(req);
160-
req.session.cookie = new Cookie(cookieOptions);
161-
162-
if (cookieOptions.secure === 'auto') {
163-
req.session.cookie.secure = issecure(req, trustProxy);
164-
}
160+
req.session.cookie = createCookie(cookieOptions, req, trustProxy);
165161
};
166162

167163
var storeImplementsTouch = typeof store.touch === 'function';
@@ -217,29 +213,47 @@ function session(options) {
217213

218214
// set-cookie
219215
onHeaders(res, function(){
216+
217+
// Is this an existing session that is being destroyed?
218+
var isDestroying = isBeingDestroyed(req);
219+
220220
if (!req.session) {
221221
debug('no session');
222-
return;
222+
if (!isDestroying || isInitialSession(req)) {
223+
return;
224+
}
223225
}
224226

225-
if (!shouldSetCookie(req)) {
226-
return;
227+
var cookie = req.session ? req.session.cookie : undefined;
228+
if (isDestroying) {
229+
if (cookie == null) {
230+
debug('creating expired cookie');
231+
cookie = createCookie(cookieOptions, req, trustProxy);
232+
}
233+
234+
// Set the cookie to immediately expire on the client
235+
cookie.maxAge = 0;
227236
}
228237

229238
// only send secure cookies via https
230-
if (req.session.cookie.secure && !issecure(req, trustProxy)) {
239+
if (cookie.secure && !issecure(req, trustProxy)) {
231240
debug('not secured');
232241
return;
233242
}
234243

235-
if (!touched) {
236-
// touch session
237-
req.session.touch()
238-
touched = true
244+
if (!isDestroying) {
245+
if (!shouldSetCookie(req)) {
246+
return;
247+
}
248+
else if (!touched) {
249+
// touch session
250+
req.session.touch();
251+
touched = true;
252+
}
239253
}
240254

241255
// set cookie
242-
setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data);
256+
setcookie(res, name, req.sessionID, secrets[0], cookie.data);
243257
});
244258

245259
// proxy end() to commit the session
@@ -396,6 +410,16 @@ function session(options) {
396410
});
397411
}
398412

413+
// check if session has been or is being destroyed
414+
function isBeingDestroyed(req) {
415+
return req.sessionID && req.session == null;
416+
}
417+
418+
// check if session is the initial session
419+
function isInitialSession(req) {
420+
return req.sessionID && cookieId != req.sessionID;
421+
}
422+
399423
// check if session has been modified
400424
function isModified(sess) {
401425
return originalId !== sess.id || originalHash !== hash(sess);
@@ -437,8 +461,8 @@ function session(options) {
437461

438462
// determine if cookie should be set on response
439463
function shouldSetCookie(req) {
440-
// cannot set cookie without a session ID
441-
if (typeof req.sessionID !== 'string') {
464+
// cannot set cookie without a session ID and a session
465+
if (typeof req.sessionID !== 'string' || !req.session) {
442466
return false;
443467
}
444468

@@ -491,6 +515,25 @@ function session(options) {
491515
};
492516
};
493517

518+
/**
519+
* Create a new Cookie for this request.
520+
*
521+
* @param {Object} cookieOptions
522+
* @param {Object} req
523+
* @param {Boolean} [trustProxy]
524+
* @return {Cookie}
525+
* @private
526+
*/
527+
function createCookie(cookieOptions, req, trustProxy) {
528+
var cookieOpts = cookieOptions || {};
529+
530+
var cookie = new Cookie(cookieOpts);
531+
if (cookieOpts.secure === 'auto') {
532+
cookie.secure = issecure(req, trustProxy);
533+
}
534+
return cookie;
535+
}
536+
494537
/**
495538
* Generate a session ID for a new session.
496539
*

0 commit comments

Comments
 (0)