-
-
Notifications
You must be signed in to change notification settings - Fork 987
Implement custom cookie signature #337
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
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 |
---|---|---|
|
@@ -78,6 +78,8 @@ var defer = typeof setImmediate === 'function' | |
* @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store | ||
* @param {String|Array} [options.secret] Secret for signing session ID | ||
* @param {Object} [options.store=MemoryStore] Session store | ||
* @param {Object} [options.signature] Object that has the same API as node-cookie-signature | ||
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. Typo: node-cookie-signature -> cookie-signature Also, I'm not sure we should define our API as "being the same as another module". Perhaps just spell out what we want and just say that |
||
if you need to implement your own signing mechanism | ||
* @param {String} [options.unset] | ||
* @return {Function} middleware | ||
* @public | ||
|
@@ -131,6 +133,16 @@ function session(options) { | |
throw new TypeError('unset option must be "destroy" or "keep"'); | ||
} | ||
|
||
var signer = signature; | ||
if (typeof opts.signature === 'object') { | ||
if (typeof opts.signature.sign !== 'function' || | ||
typeof opts.signature.unsign !== 'function') { | ||
throw new TypeError('signature option object must have sign and unsign functions'); | ||
} | ||
|
||
signer = options.signature; | ||
} | ||
|
||
// TODO: switch to "destroy" on next major | ||
var unsetDestroy = opts.unset === 'destroy' | ||
|
||
|
@@ -212,7 +224,7 @@ function session(options) { | |
req.sessionStore = store; | ||
|
||
// get the session ID from the cookie | ||
var cookieId = req.sessionID = getcookie(req, name, secrets); | ||
var cookieId = req.sessionID = getcookie(req, name, secrets, signer); | ||
|
||
// set-cookie | ||
onHeaders(res, function(){ | ||
|
@@ -235,7 +247,7 @@ function session(options) { | |
req.session.touch(); | ||
|
||
// set cookie | ||
setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data); | ||
setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data, signer); | ||
}); | ||
|
||
// proxy end() to commit the session | ||
|
@@ -483,7 +495,7 @@ function generateSessionId(sess) { | |
* @private | ||
*/ | ||
|
||
function getcookie(req, name, secrets) { | ||
function getcookie(req, name, secrets, signer) { | ||
var header = req.headers.cookie; | ||
var raw; | ||
var val; | ||
|
@@ -495,15 +507,11 @@ function getcookie(req, name, secrets) { | |
raw = cookies[name]; | ||
|
||
if (raw) { | ||
if (raw.substr(0, 2) === 's:') { | ||
val = unsigncookie(raw.slice(2), secrets); | ||
val = unsigncookie(raw, secrets, signer); | ||
|
||
if (val === false) { | ||
debug('cookie signature invalid'); | ||
val = undefined; | ||
} | ||
} else { | ||
debug('cookie unsigned') | ||
if (val === false) { | ||
debug('cookie signature missing or invalid'); | ||
val = undefined; | ||
} | ||
} | ||
} | ||
|
@@ -522,19 +530,15 @@ function getcookie(req, name, secrets) { | |
raw = req.cookies[name]; | ||
|
||
if (raw) { | ||
if (raw.substr(0, 2) === 's:') { | ||
val = unsigncookie(raw.slice(2), secrets); | ||
val = unsigncookie(raw, secrets, signer); | ||
|
||
if (val) { | ||
deprecate('cookie should be available in req.headers.cookie'); | ||
} | ||
if (val) { | ||
deprecate('cookie should be available in req.headers.cookie'); | ||
} | ||
|
||
if (val === false) { | ||
debug('cookie signature invalid'); | ||
val = undefined; | ||
} | ||
} else { | ||
debug('cookie unsigned') | ||
if (val === false) { | ||
debug('cookie signature missing or invalid'); | ||
val = undefined; | ||
} | ||
} | ||
} | ||
|
@@ -602,8 +606,8 @@ function issecure(req, trustProxy) { | |
* @private | ||
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 change is not backwards-compatible, just as a FYI. It would also make the cookies emitted from here unreadable by other modules trying to decode them without them changing. What is the purpose of this change? 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. My purpose here was that I need to have full control over the cookie's content. (My end-game is to make express-session compatible with PHP's session management). That means having a "pass-through" signature function (AKA no signature at all). I have a patch that should (in theory) turn back compatibility while still allowing me to achieve my goals. |
||
*/ | ||
|
||
function setcookie(res, name, val, secret, options) { | ||
var signed = 's:' + signature.sign(val, secret); | ||
function setcookie(res, name, val, secret, options, signer) { | ||
var signed = signer.sign(val, secret); | ||
var data = cookie.serialize(name, signed, options); | ||
|
||
debug('set-cookie %s', data); | ||
|
@@ -624,9 +628,9 @@ function setcookie(res, name, val, secret, options) { | |
* @returns {String|Boolean} | ||
* @private | ||
*/ | ||
function unsigncookie(val, secrets) { | ||
function unsigncookie(val, secrets, signer) { | ||
for (var i = 0; i < secrets.length; i++) { | ||
var result = signature.unsign(val, secrets[i]); | ||
var result = signer.unsign(val, secrets[i]); | ||
|
||
if (result !== false) { | ||
return result; | ||
|
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.
Typo here, as this module uses the
cookie-signature
module, notnode-cookie-signature
.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 could probably include a link to the npm page for the module as well.