Skip to content

Commit c9102e4

Browse files
committed
Expire cookie immediately upon destroying session
Fixes #241.
1 parent 8e57b21 commit c9102e4

File tree

2 files changed

+431
-20
lines changed

2 files changed

+431
-20
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
@@ -380,6 +394,16 @@ function session(options) {
380394
});
381395
}
382396

397+
// check if session has been or is being destroyed
398+
function isBeingDestroyed(req) {
399+
return req.sessionID && req.session == null;
400+
}
401+
402+
// check if session is the initial session
403+
function isInitialSession(req) {
404+
return req.sessionID && cookieId != req.sessionID;
405+
}
406+
383407
// check if session has been modified
384408
function isModified(sess) {
385409
return originalId !== sess.id || originalHash !== hash(sess);
@@ -421,8 +445,8 @@ function session(options) {
421445

422446
// determine if cookie should be set on response
423447
function shouldSetCookie(req) {
424-
// cannot set cookie without a session ID
425-
if (typeof req.sessionID !== 'string') {
448+
// cannot set cookie without a session ID and a session
449+
if (typeof req.sessionID !== 'string' || !req.session) {
426450
return false;
427451
}
428452

@@ -475,6 +499,25 @@ function session(options) {
475499
};
476500
};
477501

502+
/**
503+
* Create a new Cookie for this request.
504+
*
505+
* @param {Object} cookieOptions
506+
* @param {Object} req
507+
* @param {Boolean} [trustProxy]
508+
* @return {Cookie}
509+
* @private
510+
*/
511+
function createCookie(cookieOptions, req, trustProxy) {
512+
var cookieOpts = cookieOptions || {};
513+
514+
var cookie = new Cookie(cookieOpts);
515+
if (cookieOpts.secure === 'auto') {
516+
cookie.secure = issecure(req, trustProxy);
517+
}
518+
return cookie;
519+
}
520+
478521
/**
479522
* Generate a session ID for a new session.
480523
*

0 commit comments

Comments
 (0)