diff --git a/src/lib/AuthenticationRegulator.ts b/src/lib/AuthenticationRegulator.ts new file mode 100644 index 000000000..77c121b2f --- /dev/null +++ b/src/lib/AuthenticationRegulator.ts @@ -0,0 +1,44 @@ + +import * as Promise from "bluebird"; + +const exceptions = require("./exceptions"); + +const REGULATION_TRACE_TYPE = "regulation"; +const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3; + +interface DatedDocument { + date: Date; +} + +export class AuthenticationRegulator { + _user_data_store: any; + _lock_time_in_seconds: number; + + constructor(user_data_store: any, lock_time_in_seconds: number) { + this._user_data_store = user_data_store; + this._lock_time_in_seconds = lock_time_in_seconds; + } + + // Mark authentication + mark(userid: string, is_success: boolean): Promise { + return this._user_data_store.save_authentication_trace(userid, REGULATION_TRACE_TYPE, is_success); + } + + regulate(userid: string): Promise { + return this._user_data_store.get_last_authentication_traces(userid, REGULATION_TRACE_TYPE, false, 3) + .then((docs: Array) => { + if (docs.length < MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE) { + // less than the max authorized number of authentication in time range, thus authorizing access + return Promise.resolve(); + } + + const oldest_doc = docs[MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE - 1]; + const no_lock_min_date = new Date(new Date().getTime() - this._lock_time_in_seconds * 1000); + if (oldest_doc.date > no_lock_min_date) { + throw new exceptions.AuthenticationRegulationError("Max number of authentication. Please retry in few minutes."); + } + + return Promise.resolve(); + }); + } +} diff --git a/src/lib/authentication_regulator.js b/src/lib/authentication_regulator.js deleted file mode 100644 index e7e221908..000000000 --- a/src/lib/authentication_regulator.js +++ /dev/null @@ -1,35 +0,0 @@ - -module.exports = AuthenticationRegulator; - -var exceptions = require('./exceptions'); -var Promise = require('bluebird'); - -function AuthenticationRegulator(user_data_store, lock_time_in_seconds) { - this._user_data_store = user_data_store; - this._lock_time_in_seconds = lock_time_in_seconds; -} - -// Mark authentication -AuthenticationRegulator.prototype.mark = function(userid, is_success) { - return this._user_data_store.save_authentication_trace(userid, '1stfactor', is_success); -} - -AuthenticationRegulator.prototype.regulate = function(userid) { - var that = this; - return this._user_data_store.get_last_authentication_traces(userid, '1stfactor', false, 3) - .then(function(docs) { - if(docs.length < 3) { - return Promise.resolve(); - } - - var oldest_doc = docs[2]; - var no_lock_min_date = new Date(new Date().getTime() - - that._lock_time_in_seconds * 1000); - - if(oldest_doc.date > no_lock_min_date) { - throw new exceptions.AuthenticationRegulationError(); - } - - return Promise.resolve(); - }); -} diff --git a/src/lib/server.ts b/src/lib/server.ts index 279c3fbda..8e6ca8a89 100644 --- a/src/lib/server.ts +++ b/src/lib/server.ts @@ -3,10 +3,10 @@ import { authelia } from "../types/authelia"; import * as Express from "express"; import * as BodyParser from "body-parser"; import * as Path from "path"; +import { AuthenticationRegulator } from "./AuthenticationRegulator"; const UserDataStore = require("./user_data_store"); const Notifier = require("./notifier"); -const AuthenticationRegulator = require("./authentication_regulator"); const setup_endpoints = require("./setup_endpoints"); const config_adapter = require("./config_adapter"); const Ldap = require("./ldap"); diff --git a/src/types/authelia.d.ts b/src/types/authelia.d.ts index 9b2223566..94950cbbb 100644 --- a/src/types/authelia.d.ts +++ b/src/types/authelia.d.ts @@ -3,7 +3,6 @@ import * as winston from "winston"; import * as nedb from "nedb"; declare namespace authelia { - interface LdapConfiguration { url: string; base_dn: string; diff --git a/test/unitary/test_authentication_regulator.js b/test/unitary/AuthenticationRegulator.test.js similarity index 86% rename from test/unitary/test_authentication_regulator.js rename to test/unitary/AuthenticationRegulator.test.js index 18b46c9ec..c06e91e29 100644 --- a/test/unitary/test_authentication_regulator.js +++ b/test/unitary/AuthenticationRegulator.test.js @@ -1,11 +1,12 @@ -var AuthenticationRegulator = require('../../src/lib/authentication_regulator'); -var UserDataStore = require('../../src/lib/user_data_store'); -var DataStore = require('nedb'); +import { AuthenticationRegulator } from "../../src/lib/AuthenticationRegulator"; +import * as UserDataStore from "../../src/lib/user_data_store"; +import * as DataStore from "nedb"; +import * as MockDate from "mockdate"; + var exceptions = require('../../src/lib/exceptions'); -var MockDate = require('mockdate'); -describe('test authentication regulator', function() { +describe.only('test authentication regulator', function() { it('should mark 2 authentication and regulate (resolve)', function() { var options = {}; options.inMemoryOnly = true; diff --git a/test/unitary/config_adapter.test.ts b/test/unitary/config_adapter.test.ts index 3db5cd58a..51a4eef9d 100644 --- a/test/unitary/config_adapter.test.ts +++ b/test/unitary/config_adapter.test.ts @@ -1,4 +1,3 @@ -import * as mocha from "mocha"; import * as Assert from "assert"; const config_adapter = require("../../src/lib/config_adapter");