diff --git a/HISTORY.md b/HISTORY.md index 90b8d59..f648b1b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========== * Pass invalid csrf token error to `next()` instead of throwing + * Pass misconfigured error to `next()` instead of throwing * Provide misconfigured error when using cookies without cookie-parser * deps: cookie@0.2.4 - perf: enable strict mode diff --git a/index.js b/index.js index e72e627..6d077a2 100644 --- a/index.js +++ b/index.js @@ -66,6 +66,12 @@ function csurf (options) { var ignoreMethod = getIgnoredMethods(ignoreMethods) return function csrf (req, res, next) { + // validate the configuration against request + if (!verifyConfiguration(req, sessionKey, cookie)) { + return next(new Error('misconfigured csrf')) + } + + // get the secret from the request var secret = getSecret(req, sessionKey, cookie) var token @@ -190,28 +196,40 @@ function getIgnoredMethods (methods) { */ function getSecret (req, sessionKey, cookie) { - var bag - var key + // get the bag & key + var bag = getSecretBag(req, sessionKey, cookie) + var key = cookie ? cookie.key : 'csrfSecret' + + if (!bag) { + /* istanbul ignore next: should never actually run */ + throw new Error('misconfigured csrf') + } + + // return secret from bag + return bag[key] +} + +/** + * Get the token secret bag from the request. + * + * @param {IncomingMessage} req + * @param {String} sessionKey + * @param {Object} [cookie] + * @api private + */ +function getSecretBag (req, sessionKey, cookie) { if (cookie) { // get secret from cookie var cookieKey = cookie.signed ? 'signedCookies' : 'cookies' - bag = req[cookieKey] - key = cookie.key + return req[cookieKey] } else { // get secret from session - bag = req[sessionKey] - key = 'csrfSecret' - } - - if (!bag) { - throw new Error('misconfigured csrf') + return req[sessionKey] } - - return bag[key] } /** @@ -253,7 +271,8 @@ function setSecret (req, res, sessionKey, val, cookie) { var secret = req.secret if (!secret) { - throw new Error('cookieParser("secret") required for signed cookies') + /* istanbul ignore next: should never actually run */ + throw new Error('misconfigured csrf') } val = 's:' + sign(val, secret) @@ -268,3 +287,20 @@ function setSecret (req, res, sessionKey, val, cookie) { throw new Error('misconfigured csrf') } } + +/** + * Verify the configuration against the request. + * @private + */ + +function verifyConfiguration (req, sessionKey, cookie) { + if (!getSecretBag(req, sessionKey, cookie)) { + return false + } + + if (cookie && cookie.signed && !req.secret) { + return false + } + + return true +} diff --git a/test/test.js b/test/test.js index 906c3c6..2f164b7 100644 --- a/test/test.js +++ b/test/test.js @@ -257,7 +257,7 @@ describe('csurf', function () { request(app) .get('/') - .expect(500, /cookieParser.*secret/, done) + .expect(500, /misconfigured csrf/, done) }) describe('with "ignoreMethods" option', function () {