UNPKG

double-submit-cookies

Version:
81 lines (69 loc) 2.51 kB
'use strict'; var jwt = require('jsonwebtoken'), nonce = require('nonce')(), cookieParser = require('cookie-parser'), ejwt = require('./express-jwt'), crypto = require('./crypto'); module.exports = { addDSCookies: _addDSCookies, clearDSCookies: _clearDSCookies, jwtTokenVerifier: _jwtTokenVerifier }; // Exposed methods function _addDSCookies(options) { var xsrfToken = generateRandomCsrfToken(), claims = getClaimFromData(options.data, xsrfToken), token = jwt.sign(claims, options.jwtSecret, { expiresIn: options.jwtTokenExpirationInMinutes * 60 }); if (options.header) { // Use headers instead of cookies options.res.setHeader("x-token", token); options.res.setHeader("x-xsrf-token", xsrfToken); } else { // Set JWT token in secure/http only cookie options.res.cookie('token', token, { maxAge: (options.jwtTokenExpirationInMinutes * 60 * 1000), secure: (typeof options.secure === 'undefined') ? true : options.secure, httpOnly: true }); // Generate additional cookie to implement double-submit cookie protection // https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet options.res.cookie('xsrf-token', xsrfToken, { secure: (typeof options.secure === 'undefined') ? true : options.secure }); } } function _clearDSCookies(options) { options.res.clearCookie('token'); options.res.clearCookie('xsrf-token'); } function _jwtTokenVerifier(app, options) { app.use(cookieParser()); app.use(ejwt( { secret: options.jwtSecret, algorithms: [options.jwtAlgorithm], // Allow only a single algorithm we use getToken: function fromCookie (req) { // For now accept only tokens stored in secure cookies if (req.cookies && req.cookies.token) { return req.cookies.token; } // Return token if it is stored in header if (req.headers && req.headers['x-token']) { return req.headers['x-token']; } return null; } }).unless({ path: options.path })); } // Private methods function getClaimFromData(data, xsrfToken) { data.xsrfToken = xsrfToken; return data; } function generateRandomCsrfToken() { return encodeURIComponent(crypto.hashSha1Sync(nonce())); }