botpress
Version:
The world's first CMS for bots. Easily create, manage and extend chatbots.
195 lines (150 loc) • 5.13 kB
JavaScript
;
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