UNPKG

express-jwt-xsrf

Version:

Express filter for jwt parsing with anti-xsrf synchronizer.

107 lines 4.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const encrypt = require("crypto"); const cookies = require("cookie-parser"); const parsing = require("body-parser"); const jwtoken = require("jsonwebtoken"); /** * axsrfWithCors implementation. * * Filter defined to accept cors and validate specified bearer token integrity * according to the specified secret key and participating anti-xsrf cookie. * * @author Kirk Bulis */ function axsrfWithCors(options) { return [ parsing.json({ limit: options.jsonLimit || 64 * 1024, }), cookies('', { decode: (value) => { return value; } }), (req, res, next) => { res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers')); res.header('Access-Control-Allow-Origin', options.allowOrigin ? options.allowOrigin === '*' ? req.header('Origin') : options.allowOrigin : '*'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Vary', 'Origin'); if (options.debug === true) { console.log('~ adding cors headers'); } next(); }, (req, res, next) => { if (options.debug === true) { console.log('~ checking authorization token'); } try { let encoded = req.headers['authorization'] || ''; if (options.debug === true) { console.log('~ authorization header value ' + encoded); } if (encoded.length > 6 && encoded.substr(0, 6).toLowerCase() === 'bearer') { encoded = encoded.substr(7).trim(); } if (encoded.length === 0) { encoded = req.query['token'] || ''; } if (encoded === 'null') { encoded = ''; } if (encoded.length !== 0) { if (options.debug === true) { console.log('~ parsing token ' + encoded); } try { let extracted = Object.assign({}, jwtoken.verify(encoded, options.hashingSecretKey)); if (extracted.exp && extracted.exp > (+new Date / 1000)) { if (req.cookies['axsrf'] && extracted.axsrf === encrypt.createHmac(options.hashingAlgorithm, options.hashingSecretKey).update(req.cookies['axsrf']).digest('base64')) { options.identify(res, extracted); next(); return; } else { if (options.debug === true) { console.log('~ authorization token not matching axsrf cookie'); } } } else { if (options.debug === true) { console.log('~ authorization token expired'); } } } catch (eX) { if (options.debug === true) { console.log(eX); } } } } catch (eX) { } options.identify(res); next(); }, (req, res, next) => { if (!res.locals.generateTokenWithAxsrf) { res.locals.generateTokenWithAxsrf = (payload, expiresIn, onlySecure) => { const axsrf = 'a' + (Math.floor(Math.random() * 900000000000000) + 100000000000000); res.cookie('axsrf', axsrf, { httpOnly: true, secure: onlySecure, }); return jwtoken.sign(Object.assign({ axsrf: encrypt.createHmac(options.hashingAlgorithm, options.hashingSecretKey).update(axsrf).digest('base64') }, payload), options.hashingSecretKey, { expiresIn: expiresIn, }); }; } next(); }, ]; } exports.axsrfWithCors = axsrfWithCors; //# sourceMappingURL=index.js.map