@experium/nest-bruteforce-guard
Version:
Authorization protection from bruteforce
174 lines (173 loc) • 7.91 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BruteforceGuardService = void 0;
const date_fns_1 = require("date-fns");
const typeorm_1 = require("typeorm");
const escapeStringRegexp = require("escape-string-regexp");
const common_1 = require("@nestjs/common");
const typeorm_2 = require("@nestjs/typeorm");
const login_attempt_entity_1 = require("./entity/login-attempt.entity");
const constants_1 = require("./constants");
const bruteforce_detection_exception_1 = require("./exception/bruteforce-detection.exception");
const exception_catcher_registry_1 = require("./catcher/exception-catcher.registry");
let BruteforceGuardService = class BruteforceGuardService {
constructor(repository, config, registry) {
this.repository = repository;
this.config = config;
this.registry = registry;
}
canLogin(context) {
return __awaiter(this, void 0, void 0, function* () {
const login = this.getLoginByContext(context);
const ip = context.switchToHttp().getRequest().ip;
const loginAttemptsCount = yield this.getAttemptsCountByLogin(login);
const ipAttemptsCount = yield this.getAttemptsCountByIP(ip);
if (login &&
loginAttemptsCount < this.config.attemptCountByLogin &&
ipAttemptsCount < this.config.attemptCountByIp) {
return true;
}
yield this.repository.save(new login_attempt_entity_1.LoginAttempt(login, ip, true, true));
throw new bruteforce_detection_exception_1.BruteforceDetectionException();
});
}
saveErrorAttempt(context, exception) {
return __awaiter(this, void 0, void 0, function* () {
const login = this.getLoginByContext(context);
const ip = context.switchToHttp().getRequest().ip;
let loginAttempt = null;
for (const catcher of this.registry.getAll()) {
loginAttempt = catcher.handle(exception, context);
if (!!loginAttempt) {
break;
}
}
if (!loginAttempt) {
loginAttempt = new login_attempt_entity_1.LoginAttempt(login, ip, false);
}
yield this.repository.save(loginAttempt);
});
}
findByFilter(filter) {
return __awaiter(this, void 0, void 0, function* () {
return this.repository.createEntityCursor(yield this.getDefaultQuery(filter));
});
}
getDefaultQuery(filter) {
return __awaiter(this, void 0, void 0, function* () {
const query = {};
if ('login' in filter && filter.login) {
query.login = {
$regex: new RegExp(escapeStringRegexp(filter.login)),
$options: 'i',
};
}
if ('ip' in filter && filter.ip) {
query.ip = {
$regex: new RegExp(escapeStringRegexp(filter.ip)),
$options: 'i',
};
}
if ('attemptBlocked' in filter && typeof filter.attemptBlocked === 'boolean') {
query.attemptBlocked = filter.attemptBlocked;
}
if ('loginFailure' in filter && typeof filter.loginFailure === 'boolean') {
query.loginFailure = filter.loginFailure;
}
if ('userDisabled' in filter && typeof filter.userDisabled === 'boolean') {
query.userDisabled = filter.userDisabled;
}
if ('badPassword' in filter && typeof filter.badPassword === 'boolean') {
query.badPassword = filter.badPassword;
}
if ('dateFrom' in filter && filter.dateFrom) {
query.$and = query.$and || [];
query.$and = [
...query.$and,
{
date: {
$gte: new Date(filter.dateFrom),
},
},
];
}
if ('dateTo' in filter && filter.dateTo) {
query.$and = query.$and || [];
query.$and = [
...query.$and,
{
date: {
$lte: new Date(filter.dateTo),
},
},
];
}
return query;
});
}
saveSuccessAttempt(context) {
return __awaiter(this, void 0, void 0, function* () {
const login = this.getLoginByContext(context);
const ip = context.switchToHttp().getRequest().ip;
yield this.repository.save(new login_attempt_entity_1.LoginAttempt(login, ip));
});
}
save(entity) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.repository.save(entity);
});
}
getAttemptsCountByLogin(login) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.repository.count({
login,
date: {
$gt: date_fns_1.addMinutes(new Date(), -this.config.attemptMinutesByLogin),
},
loginFailure: true,
});
});
}
getAttemptsCountByIP(ip) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.repository.count({
ip,
date: {
$gt: date_fns_1.addMinutes(new Date(), -this.config.attemptMinutesByIp),
},
loginFailure: true,
});
});
}
getLoginByContext(context) {
const loginField = this.config.loginField;
return context.switchToHttp().getRequest().body[loginField];
}
};
BruteforceGuardService = __decorate([
__param(0, typeorm_2.InjectRepository(login_attempt_entity_1.LoginAttempt)),
__param(1, common_1.Inject(constants_1.BRUTEFORCE_GUARD_OPTIONS_PROVIDER)),
__metadata("design:paramtypes", [typeorm_1.MongoRepository, Object, exception_catcher_registry_1.ExceptionCatcherRegistry])
], BruteforceGuardService);
exports.BruteforceGuardService = BruteforceGuardService;