description and source-codefunction csurf(options) {
var opts = options || {}
// get cookie options
var cookie = getCookieOptions(opts.cookie)
// get session options
var sessionKey = opts.sessionKey || 'session'
// get value getter
var value = opts.value || defaultValue
// token repo
var tokens = new Tokens(opts)
// ignored methods
var ignoreMethods = opts.ignoreMethods === undefined
? ['GET', 'HEAD', 'OPTIONS']
: opts.ignoreMethods
if (!Array.isArray(ignoreMethods)) {
throw new TypeError('option ignoreMethods must be an array')
}
// generate lookup
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
// lazy-load token getter
req.csrfToken = function csrfToken () {
var sec = !cookie
? getSecret(req, sessionKey, cookie)
: secret
// use cached token if secret has not changed
if (token && sec === secret) {
return token
}
// generate & set new secret
if (sec === undefined) {
sec = tokens.secretSync()
setSecret(req, res, sessionKey, sec, cookie)
}
// update changed secret
secret = sec
// create new token
token = tokens.create(secret)
return token
}
// generate & set secret
if (!secret) {
secret = tokens.secretSync()
setSecret(req, res, sessionKey, secret, cookie)
}
// verify the incoming token
if (!ignoreMethod[req.method] && !tokens.verify(secret, value(req))) {
return next(createError(403, 'invalid csrf token', {
code: 'EBADCSRFTOKEN'
}))
}
next()
}
}