UNPKG

@becomes/cms

Version:

Simple CMS for building APIs.

132 lines 5.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.APISecurity = void 0; var crypto = require("crypto"); var purple_cheetah_1 = require("purple-cheetah"); var key_cash_service_1 = require("./key-cash.service"); var APISecurity = (function () { function APISecurity() { } APISecurity.sign = function (config) { var data = { key: config.key.id, timestamp: Date.now(), nonce: crypto.randomBytes(16).toString('hex').substring(0, 6), signature: '', }; var payloadAsString = ''; if (typeof config.payload === 'object') { payloadAsString = Buffer.from(encodeURIComponent(JSON.stringify(config.payload))).toString('base64'); } else { payloadAsString = '' + config.payload; } var hmac = crypto.createHmac('sha256', config.key.secret); hmac.update(data.nonce + data.timestamp + data.key + payloadAsString); data.signature = hmac.digest('hex'); return data; }; APISecurity.verify = function (data, payload, requestMethod, path, skipAccess) { path = path.split('?')[0]; if (typeof data.key === 'undefined') { throw new Error("Missing property 'key'."); } if (typeof data.nonce === 'undefined') { throw new Error("Missing property 'nonce'."); } if (typeof data.timestamp === 'undefined') { throw new Error("Missing property 'timestamp'."); } else { if (typeof data.timestamp === 'string') { data.timestamp = parseInt(data.timestamp, 10); } } if (typeof data.signature === 'undefined') { throw new Error("Missing property 'signature'."); } if (purple_cheetah_1.StringUtility.isIdValid(data.key) === false) { throw new Error("Invalid 'key' value was provided."); } var key = key_cash_service_1.KeyCashService.findById(data.key); if (key === null) { throw new Error("Invalid 'key' was provided."); } if (key.blocked === true) { throw new Error('This Key is blocked.'); } var payloadAsString = ''; if (typeof payload === 'object') { payloadAsString = Buffer.from(encodeURIComponent(JSON.stringify(payload))).toString('base64'); } else { payloadAsString = '' + payload; } if (data.timestamp < Date.now() - 60000 || data.timestamp > Date.now() + 3000) { throw new Error('Timestamp out of range.'); } var hmac = crypto.createHmac('sha256', key.secret); hmac.update(data.nonce + data.timestamp + data.key + payloadAsString); var signature = hmac.digest('hex'); if (signature !== data.signature) { throw new Error('Invalid signature.'); } if (skipAccess && skipAccess === true) { return; } if (APISecurity.verifyAccess(key, requestMethod, path) === false) { throw new Error("Key is not allowed to access this resource."); } }; APISecurity.verifyAccess = function (key, method, path) { if (path.startsWith('/function')) { var p_1 = path.replace('/function/', ''); if (key.access.functions.find(function (e) { return e.name === p_1; }) && method === 'POST') { return true; } } else if (path.startsWith('/template')) { var parts_1 = path.split('/'); if (parts_1.length > 1) { if (parts_1.length === 3) { if (parts_1[2] === 'all' && method === 'GET') { var templateAccess = key.access.templates.find(function (e) { return e.methods.find(function (m) { return m === 'GET_ALL'; }); }); if (templateAccess) { return true; } } else if (method === 'GET') { var templateAccess = key.access.templates.find(function (e) { return e._id === parts_1[2]; }); if (templateAccess) { if (templateAccess.methods.find(function (e) { return e === method; })) { return true; } } } } else if (parts_1.length > 2 && parts_1[3] === 'entry') { var templateAccess = key.access.templates.find(function (e) { return e._id === parts_1[2]; }); if (templateAccess) { if (parts_1.length === 5 && parts_1[4] === 'all') { if (templateAccess.entry.methods.find(function (e) { return e === 'GET_ALL'; })) { return true; } } else { if (templateAccess.entry.methods.find(function (e) { return e === method; })) { return true; } } } } } } return false; }; return APISecurity; }()); exports.APISecurity = APISecurity; //# sourceMappingURL=api-security.js.map