Comparing version 1.3.0 to 1.4.0
@@ -0,1 +1,7 @@ | ||
1.4.0 / 2014-07-30 | ||
================== | ||
* Support changing `req.session` after `csurf` middleware | ||
- Calling `res.csrfToken()` after `req.session.destroy()` will now work | ||
1.3.0 / 2014-07-03 | ||
@@ -2,0 +8,0 @@ ================== |
195
index.js
/*! | ||
* Expressjs | Connect - csrf | ||
* csurf | ||
* Copyright(c) 2011 Sencha Inc. | ||
@@ -35,82 +35,56 @@ * Copyright(c) 2014 Jonathan Ong | ||
module.exports = function csrf(options) { | ||
module.exports = function csurf(options) { | ||
options = options || {}; | ||
var value = options.value || defaultValue, | ||
cookie = options.cookie, | ||
cookieKey = (cookie && cookie.key) || '_csrf', | ||
signedCookie = cookie && cookie.signed; | ||
// get value getter | ||
var value = options.value || defaultValue | ||
// token repo | ||
var tokens = csrfTokens(options); | ||
if (cookie && typeof cookie !== 'object') | ||
cookie = {}; | ||
// default cookie key | ||
if (options.cookie && !options.cookie.key) { | ||
options.cookie.key = '_csrf' | ||
} | ||
return function(req, res, next){ | ||
return function csrf(req, res, next) { | ||
var secret = getsecret(req, options.cookie) | ||
var token | ||
// already have one | ||
var secret; | ||
if (cookie) { | ||
secret = ( (signedCookie | ||
&& req.signedCookies | ||
&& req.signedCookies[cookieKey]) | ||
|| (!signedCookie | ||
&& req.cookies | ||
&& req.cookies[cookieKey]) | ||
); | ||
} else if (req.session) | ||
secret = req.session.csrfSecret; | ||
else { | ||
var err = new Error('misconfigured csrf'); | ||
err.status = 500; | ||
next(err); | ||
return; | ||
} | ||
if (secret) return createToken(secret); | ||
// lazy-load token getter | ||
req.csrfToken = function csrfToken() { | ||
var sec = !options.cookie | ||
? getsecret(req, options.cookie) | ||
: secret | ||
// generate secret | ||
tokens.secret(function(err, secret){ | ||
if (err) return next(err); | ||
if (cookie) { | ||
var cookieSecret = req.secret; | ||
var val = secret; | ||
// use cached token if secret has not changed | ||
if (token && sec === secret) { | ||
return token | ||
} | ||
if (signedCookie) { | ||
if (!cookieSecret) { | ||
var err = new Error('cookieParser("secret") required for signed cookies'); | ||
err.status = 500; | ||
next(err); | ||
return; | ||
} | ||
// generate & set new secret | ||
if (sec === undefined) { | ||
sec = tokens.secretSync() | ||
setsecret(req, res, sec, options.cookie) | ||
} | ||
val = 's:' + sign(secret, cookieSecret); | ||
} | ||
// update changed secret | ||
secret = sec | ||
setcookie(res, cookieKey, val, cookie); | ||
} else { | ||
req.session.csrfSecret = secret; | ||
} | ||
createToken(secret); | ||
}); | ||
// create new token | ||
token = tokens.create(secret) | ||
// generate the token | ||
function createToken(secret) { | ||
// lazy-load token | ||
var token; | ||
req.csrfToken = function csrfToken() { | ||
return token || (token = tokens.create(secret)); | ||
}; | ||
return token | ||
} | ||
// ignore these methods | ||
if (ignoreMethod[req.method]) return next(); | ||
// generate & set secret | ||
if (!secret) { | ||
secret = tokens.secretSync() | ||
setsecret(req, res, secret, options.cookie) | ||
} | ||
// check user-submitted value | ||
if (!tokens.verify(secret, value(req))) { | ||
var err = new Error('invalid csrf token'); | ||
err.status = 403; | ||
next(err); | ||
return; | ||
} | ||
// verify the incoming token | ||
verifytoken(req, tokens, secret, value(req)) | ||
next(); | ||
} | ||
next() | ||
} | ||
@@ -136,2 +110,30 @@ }; | ||
/** | ||
* Get the token secret from the request. | ||
* | ||
* @param {IncomingMessage} req | ||
* @param {Object} [cookie] | ||
* @api private | ||
*/ | ||
function getsecret(req, cookie) { | ||
var secret | ||
if (cookie) { | ||
// get secret from cookie | ||
var bag = cookie.signed | ||
? 'signedCookies' | ||
: 'cookies' | ||
secret = req[bag][cookie.key] | ||
} else if (req.session) { | ||
// get secret from session | ||
secret = req.session.csrfSecret | ||
} else { | ||
throw new Error('misconfigured csrf') | ||
} | ||
return secret | ||
} | ||
/** | ||
* Set a cookie on the HTTP response. | ||
@@ -156,1 +158,60 @@ * | ||
} | ||
/** | ||
* Set the token secret on the request. | ||
* | ||
* @param {IncomingMessage} req | ||
* @param {OutgoingMessage} res | ||
* @param {string} val | ||
* @param {Object} [cookie] | ||
* @api private | ||
*/ | ||
function setsecret(req, res, val, cookie) { | ||
if (cookie) { | ||
// set secret on cookie | ||
if (cookie.signed) { | ||
var secret = req.secret | ||
if (!secret) { | ||
throw new Error('cookieParser("secret") required for signed cookies') | ||
} | ||
val = 's:' + sign(val, secret) | ||
} | ||
setcookie(res, cookie.key, val, cookie); | ||
} else if (req.session) { | ||
// set secret on session | ||
req.session.csrfSecret = val | ||
} else { | ||
/* istanbul ignore next: should never actually run */ | ||
throw new Error('misconfigured csrf') | ||
} | ||
} | ||
/** | ||
* Verify the token. | ||
* | ||
* @param {IncomingMessage} req | ||
* @param {Object} tokens | ||
* @param {string} secret | ||
* @param {string} val | ||
* @api private | ||
*/ | ||
function verifytoken(req, tokens, secret, val) { | ||
// ignore these methods | ||
if (ignoreMethod[req.method]) { | ||
return | ||
} | ||
// valid token | ||
if (tokens.verify(secret, val)) { | ||
return | ||
} | ||
var err = new Error('invalid csrf token') | ||
err.status = 403 | ||
throw err | ||
} |
{ | ||
"name": "csurf", | ||
"description": "CSRF token middleware", | ||
"version": "1.3.0", | ||
"author": { | ||
"name": "Jonathan Ong", | ||
"email": "me@jongleberry.com", | ||
"url": "http://jongleberry.com", | ||
"twitter": "https://twitter.com/jongleberry" | ||
}, | ||
"version": "1.4.0", | ||
"author": "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)", | ||
"contributors": [ | ||
"Douglas Christopher Wilson <doug@somethingdoug.com>" | ||
], | ||
"license": "MIT", | ||
@@ -19,8 +17,8 @@ "repository": "expressjs/csurf", | ||
"devDependencies": { | ||
"body-parser": "~1.3.0", | ||
"body-parser": "~1.5.2", | ||
"connect": "3", | ||
"cookie-parser": "~1.3.1", | ||
"cookie-session": "~1.0.2", | ||
"istanbul": "0.2.14", | ||
"mocha": "~1.20.1", | ||
"istanbul": "0.3.0", | ||
"mocha": "~1.21.3", | ||
"should": "~4.0.4", | ||
@@ -27,0 +25,0 @@ "supertest": "~0.13.0" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
9054
176
0