UNPKG

botpress

Version:

The world's first CMS for bots. Easily create, manage and extend chatbots.

195 lines (150 loc) 5.13 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto); var _jsonwebtoken = require('jsonwebtoken'); var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken); var _provider = require('../provider'); var _provider2 = _interopRequireDefault(_provider); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } class RootAuthentication extends _provider2.default { constructor(options) { super(options); this._bootstrapToken(); this.attempts = {}; } _bootstrapToken() { let secret = ''; const secretPath = _path2.default.join(this.dataLocation, 'secret.key'); const createNewSecret = () => { secret = _crypto2.default.randomBytes(256).toString(); _fs2.default.writeFileSync(secretPath, secret); return secret; }; if (_fs2.default.existsSync(secretPath)) { secret = _fs2.default.readFileSync(secretPath); } if (!secret || secret.length < 15) { secret = createNewSecret(); } this.secret = secret; } _buildToken(loginUser) { var _this = this; return _asyncToGenerator(function* () { return _jsonwebtoken2.default.sign({ user: loginUser }, _this.secret, { issuer: 'bot.root', expiresIn: _this.securityConfig.tokenExpiry, algorithm: 'HS256' }); })(); } _attempt(ip) { const { maxAttempts, resetAfter } = this.securityConfig; // reset the cache if time elapsed if (new Date() - this.lastCleanTimestamp >= resetAfter) { this.attempts = {}; this.lastCleanTimestamp = new Date(); } return (this.attempts[ip] || 0) < maxAttempts; } _login(user, password, ip = 'all') { var _this2 = this; return _asyncToGenerator(function* () { const adminPassword = process.env.BOTPRESS_ADMIN_PASSWORD || _this2.securityConfig.password; if (typeof user === 'string' && user.toLowerCase() === 'admin' && typeof password === 'string' && password === adminPassword) { _this2.attempts[ip] = 0; return { id: 0, username: 'admin', email: 'admin@botpress.io', first_name: 'Admin', last_name: 'Admin', avatar_url: null, roles: ['admin'] }; } else { _this2.attempts[ip] = (_this2.attempts[ip] || 0) + 1; return null; } })(); } login(user, password, ip = 'all') { var _this3 = this; return _asyncToGenerator(function* () { const canAttempt = _this3._attempt(ip); if (!canAttempt) { return { success: false, reason: 'Too many login attempts. Try again later.' }; } const loginUser = yield _this3._login(user, password, ip); if (loginUser) { return { success: true, token: yield _this3._buildToken(loginUser) }; } else { return { success: false, reason: 'Bad username / password' }; } })(); } authenticateWithError(authHeader) { var _this4 = this; return _asyncToGenerator(function* () { const [scheme, token] = (authHeader || 'invalid header').split(' '); if (scheme.toLowerCase() !== 'bearer') { throw new Error(`Wrong scheme ${scheme}, expected Bearer`); } const decoded = _jsonwebtoken2.default.verify(token, _this4.secret, { algorithms: ['HS256'] }); if (decoded.identity_proof_only) { return false; } return decoded.user; })(); } getAuthenticationInfo() { return { type: 'root' }; } refreshToken(authHeader) { var _this5 = this; return _asyncToGenerator(function* () { try { const loginUser = yield _this5.authenticateWithError(authHeader); return { success: true, token: yield _this5.buildToken(loginUser) }; } catch (err) { return { success: false, reason: err.message || 'The token is invalid or expired' }; } })(); } getUserIdentity(token) { var _this6 = this; return _asyncToGenerator(function* () { return _this6.authenticateWithError('bearer ' + token); })(); } getJWTSecretOrCertificate() { var _this7 = this; return _asyncToGenerator(function* () { return _this7.secret; })(); } } exports.default = RootAuthentication; //# sourceMappingURL=index.js.map