mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
Move exceptions to typescript
This commit is contained in:
parent
ba80bbd219
commit
bada70cf64
|
@ -1,7 +1,6 @@
|
|||
|
||||
import * as Promise from "bluebird";
|
||||
|
||||
const exceptions = require("./exceptions");
|
||||
import exceptions = require("./Exceptions");
|
||||
|
||||
const REGULATION_TRACE_TYPE = "regulation";
|
||||
const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3;
|
||||
|
|
49
src/lib/Exceptions.ts
Normal file
49
src/lib/Exceptions.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
|
||||
export class LdapSeachError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "LdapSeachError";
|
||||
Object.setPrototypeOf(this, LdapSeachError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class LdapBindError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "LdapBindError";
|
||||
Object.setPrototypeOf(this, LdapBindError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class IdentityError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "IdentityError";
|
||||
Object.setPrototypeOf(this, IdentityError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class AccessDeniedError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "AccessDeniedError";
|
||||
Object.setPrototypeOf(this, AccessDeniedError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class AuthenticationRegulationError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "AuthenticationRegulationError";
|
||||
Object.setPrototypeOf(this, AuthenticationRegulationError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidTOTPError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
this.name = "InvalidTOTPError";
|
||||
Object.setPrototypeOf(this, InvalidTOTPError.prototype);
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ export default class Server {
|
|||
const five_minutes = 5 * 60;
|
||||
const data_store = new UserDataStore(datastore_options);
|
||||
const regulator = new AuthenticationRegulator(data_store, five_minutes);
|
||||
const notifier = NotifierFactory.build(config.notifier, deps);
|
||||
const notifier = NotifierFactory.build(config.notifier, deps.nodemailer);
|
||||
const ldap = new Ldap(deps, config.ldap);
|
||||
const accessController = new AccessController(config.access_control, deps.winston);
|
||||
const totpValidator = new TOTPValidator(deps.speakeasy);
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
module.exports = {
|
||||
LdapSearchError: LdapSearchError,
|
||||
LdapBindError: LdapBindError,
|
||||
IdentityError: IdentityError,
|
||||
AccessDeniedError: AccessDeniedError,
|
||||
AuthenticationRegulationError: AuthenticationRegulationError,
|
||||
InvalidTOTPError: InvalidTOTPError,
|
||||
}
|
||||
|
||||
function LdapSearchError(message) {
|
||||
this.name = "LdapSearchError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
LdapSearchError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function LdapBindError(message) {
|
||||
this.name = "LdapBindError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
LdapBindError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function IdentityError(message) {
|
||||
this.name = "IdentityError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
IdentityError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function AccessDeniedError(message) {
|
||||
this.name = "AccessDeniedError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
AccessDeniedError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function AuthenticationRegulationError(message) {
|
||||
this.name = "AuthenticationRegulationError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
AuthenticationRegulationError.prototype = Object.create(Error.prototype);
|
||||
|
||||
function InvalidTOTPError(message) {
|
||||
this.name = "InvalidTOTPError";
|
||||
this.message = (message || "");
|
||||
}
|
||||
InvalidTOTPError.prototype = Object.create(Error.prototype);
|
|
@ -3,7 +3,7 @@ var objectPath = require('object-path');
|
|||
var randomstring = require('randomstring');
|
||||
var Promise = require('bluebird');
|
||||
var util = require('util');
|
||||
var exceptions = require('./exceptions');
|
||||
var exceptions = require('./Exceptions');
|
||||
var fs = require('fs');
|
||||
var ejs = require('ejs');
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ module.exports = Ldap;
|
|||
|
||||
var util = require('util');
|
||||
var Promise = require('bluebird');
|
||||
var exceptions = require('./exceptions');
|
||||
var exceptions = require('./Exceptions');
|
||||
var Dovehash = require('dovehash');
|
||||
|
||||
function Ldap(deps, ldap_config) {
|
||||
|
@ -70,7 +70,7 @@ Ldap.prototype._search_in_ldap = function(base, query) {
|
|||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
reject(new exceptions.LdapSearchError(err));
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as BluebirdPromise from "bluebird";
|
|||
import * as util from "util";
|
||||
import * as fs from "fs";
|
||||
import { INotifier } from "./INotifier";
|
||||
import { Identity } from "../Identity";
|
||||
import { Identity } from "../../types/Identity";
|
||||
|
||||
import { FileSystemNotifierConfiguration } from "../Configuration";
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import * as fs from "fs";
|
|||
import * as ejs from "ejs";
|
||||
import nodemailer = require("nodemailer");
|
||||
|
||||
import { NodemailerDependencies } from "../../types/Dependencies";
|
||||
import { Identity } from "../Identity";
|
||||
import { Nodemailer } from "../../types/Dependencies";
|
||||
import { Identity } from "../../types/Identity";
|
||||
import { INotifier } from "../notifiers/INotifier";
|
||||
import { GmailNotifierConfiguration } from "../Configuration";
|
||||
|
||||
|
@ -14,9 +14,9 @@ const email_template = fs.readFileSync(__dirname + "/../../resources/email-templ
|
|||
export class GMailNotifier extends INotifier {
|
||||
private transporter: any;
|
||||
|
||||
constructor(options: GmailNotifierConfiguration, deps: NodemailerDependencies) {
|
||||
constructor(options: GmailNotifierConfiguration, nodemailer: Nodemailer) {
|
||||
super();
|
||||
const transporter = deps.createTransport({
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: "gmail",
|
||||
auth: {
|
||||
user: options.username,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
import * as BluebirdPromise from "bluebird";
|
||||
import { Identity } from "../Identity";
|
||||
import { Identity } from "../../types/Identity";
|
||||
|
||||
export abstract class INotifier {
|
||||
abstract notify(identity: Identity, subject: string, link: string): BluebirdPromise<void>;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
import { NotifierConfiguration } from "..//Configuration";
|
||||
import { NotifierDependencies } from "../../types/Dependencies";
|
||||
import { Nodemailer } from "../../types/Dependencies";
|
||||
import { INotifier } from "./INotifier";
|
||||
|
||||
import { GMailNotifier } from "./GMailNotifier";
|
||||
import { FileSystemNotifier } from "./FileSystemNotifier";
|
||||
|
||||
export class NotifierFactory {
|
||||
static build(options: NotifierConfiguration, deps: NotifierDependencies): INotifier {
|
||||
static build(options: NotifierConfiguration, nodemailer: Nodemailer): INotifier {
|
||||
if ("gmail" in options) {
|
||||
return new GMailNotifier(options.gmail, deps.nodemailer);
|
||||
return new GMailNotifier(options.gmail, nodemailer);
|
||||
}
|
||||
else if ("filesystem" in options) {
|
||||
return new FileSystemNotifier(options.filesystem);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
var first_factor = require('./routes/first_factor');
|
||||
var first_factor = require('./routes/FirstFactor');
|
||||
var second_factor = require('./routes/second_factor');
|
||||
var reset_password = require('./routes/reset_password');
|
||||
var verify = require('./routes/verify');
|
||||
|
|
76
src/lib/routes/FirstFactor.ts
Normal file
76
src/lib/routes/FirstFactor.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
|
||||
import exceptions = require("../Exceptions");
|
||||
import objectPath = require("object-path");
|
||||
import Promise = require("bluebird");
|
||||
import express = require("express");
|
||||
|
||||
export = function(req: express.Request, res: express.Response) {
|
||||
const username = req.body.username;
|
||||
const password = req.body.password;
|
||||
if (!username || !password) {
|
||||
res.status(401);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
|
||||
const logger = req.app.get("logger");
|
||||
const ldap = req.app.get("ldap");
|
||||
const config = req.app.get("config");
|
||||
const regulator = req.app.get("authentication regulator");
|
||||
const accessController = req.app.get("access controller");
|
||||
|
||||
logger.info("1st factor: Starting authentication of user \"%s\"", username);
|
||||
logger.debug("1st factor: Start bind operation against LDAP");
|
||||
logger.debug("1st factor: username=%s", username);
|
||||
|
||||
regulator.regulate(username)
|
||||
.then(function() {
|
||||
return ldap.bind(username, password);
|
||||
})
|
||||
.then(function() {
|
||||
objectPath.set(req, "session.auth_session.userid", username);
|
||||
objectPath.set(req, "session.auth_session.first_factor", true);
|
||||
logger.info("1st factor: LDAP binding successful");
|
||||
logger.debug("1st factor: Retrieve email from LDAP");
|
||||
return Promise.join(ldap.get_emails(username), ldap.get_groups(username));
|
||||
})
|
||||
.then(function(data: string[2]) {
|
||||
const emails = data[0];
|
||||
const groups = data[1];
|
||||
|
||||
if (!emails && emails.length <= 0) throw new Error("No email found");
|
||||
logger.debug("1st factor: Retrieved email are %s", emails);
|
||||
objectPath.set(req, "session.auth_session.email", emails[0]);
|
||||
|
||||
const isAllowed = accessController.isDomainAllowedForUser(username, groups);
|
||||
if (!isAllowed) throw new Error("User not allowed to visit this domain");
|
||||
|
||||
regulator.mark(username, true);
|
||||
res.status(204);
|
||||
res.send();
|
||||
})
|
||||
.catch(exceptions.LdapSeachError, function(err: Error) {
|
||||
logger.error("1st factor: Unable to retrieve email from LDAP", err);
|
||||
res.status(500);
|
||||
res.send();
|
||||
})
|
||||
.catch(exceptions.LdapBindError, function(err: Error) {
|
||||
logger.error("1st factor: LDAP binding failed");
|
||||
logger.debug("1st factor: LDAP binding failed due to ", err);
|
||||
regulator.mark(username, false);
|
||||
res.status(401);
|
||||
res.send("Bad credentials");
|
||||
})
|
||||
.catch(exceptions.AuthenticationRegulationError, function(err: Error) {
|
||||
logger.error("1st factor: the regulator rejected the authentication of user %s", username);
|
||||
logger.debug("1st factor: authentication rejected due to %s", err);
|
||||
res.status(403);
|
||||
res.send("Access has been restricted for a few minutes...");
|
||||
})
|
||||
.catch(function(err: Error) {
|
||||
console.log(err.stack);
|
||||
logger.error("1st factor: Unhandled error %s", err);
|
||||
res.status(500);
|
||||
res.send("Internal error");
|
||||
});
|
||||
};
|
|
@ -1,95 +0,0 @@
|
|||
|
||||
module.exports = first_factor;
|
||||
|
||||
var exceptions = require('../exceptions');
|
||||
var objectPath = require('object-path');
|
||||
var Promise = require('bluebird');
|
||||
|
||||
function get_allowed_domains(access_control, username, groups) {
|
||||
var allowed_domains = [];
|
||||
|
||||
for(var i = 0; i<access_control.length; ++i) {
|
||||
var rule = access_control[i];
|
||||
if('allowed_domains' in rule) {
|
||||
if('group' in rule && groups.indexOf(rule['group']) >= 0) {
|
||||
var domains = rule.allowed_domains;
|
||||
allowed_domains = allowed_domains.concat(domains);
|
||||
}
|
||||
else if('user' in rule && username == rule['user']) {
|
||||
var domains = rule.allowed_domains;
|
||||
allowed_domains = allowed_domains.concat(domains);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowed_domains;
|
||||
}
|
||||
|
||||
function first_factor(req, res) {
|
||||
var username = req.body.username;
|
||||
var password = req.body.password;
|
||||
if(!username || !password) {
|
||||
res.status(401);
|
||||
res.send();
|
||||
return;
|
||||
}
|
||||
|
||||
var logger = req.app.get('logger');
|
||||
var ldap = req.app.get('ldap');
|
||||
var config = req.app.get('config');
|
||||
var regulator = req.app.get('authentication regulator');
|
||||
var accessController = req.app.get('access controller');
|
||||
|
||||
logger.info('1st factor: Starting authentication of user "%s"', username);
|
||||
logger.debug('1st factor: Start bind operation against LDAP');
|
||||
logger.debug('1st factor: username=%s', username);
|
||||
|
||||
regulator.regulate(username)
|
||||
.then(function() {
|
||||
return ldap.bind(username, password);
|
||||
})
|
||||
.then(function() {
|
||||
objectPath.set(req, 'session.auth_session.userid', username);
|
||||
objectPath.set(req, 'session.auth_session.first_factor', true);
|
||||
logger.info('1st factor: LDAP binding successful');
|
||||
logger.debug('1st factor: Retrieve email from LDAP');
|
||||
return Promise.join(ldap.get_emails(username), ldap.get_groups(username));
|
||||
})
|
||||
.then(function(data) {
|
||||
var emails = data[0];
|
||||
var groups = data[1];
|
||||
var allowed_domains;
|
||||
|
||||
if(!emails && emails.length <= 0) throw new Error('No email found');
|
||||
logger.debug('1st factor: Retrieved email are %s', emails);
|
||||
objectPath.set(req, 'session.auth_session.email', emails[0]);
|
||||
|
||||
allowed_domains = accessController.isDomainAllowedForUser(username, groups);
|
||||
|
||||
regulator.mark(username, true);
|
||||
res.status(204);
|
||||
res.send();
|
||||
})
|
||||
.catch(exceptions.LdapSearchError, function(err) {
|
||||
logger.error('1st factor: Unable to retrieve email from LDAP', err);
|
||||
res.status(500);
|
||||
res.send();
|
||||
})
|
||||
.catch(exceptions.LdapBindError, function(err) {
|
||||
logger.error('1st factor: LDAP binding failed');
|
||||
logger.debug('1st factor: LDAP binding failed due to ', err);
|
||||
regulator.mark(username, false);
|
||||
res.status(401);
|
||||
res.send('Bad credentials');
|
||||
})
|
||||
.catch(exceptions.AuthenticationRegulationError, function(err) {
|
||||
logger.error('1st factor: the regulator rejected the authentication of user %s', username);
|
||||
logger.debug('1st factor: authentication rejected due to %s', err);
|
||||
res.status(403);
|
||||
res.send('Access has been restricted for a few minutes...');
|
||||
})
|
||||
.catch(function(err) {
|
||||
logger.error('1st factor: Unhandled error %s', err);
|
||||
res.status(500);
|
||||
res.send('Internal error');
|
||||
});
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
var Promise = require('bluebird');
|
||||
var objectPath = require('object-path');
|
||||
var exceptions = require('../exceptions');
|
||||
var exceptions = require('../Exceptions');
|
||||
var CHALLENGE = 'reset-password';
|
||||
|
||||
var icheck_interface = {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
module.exports = totp_fn;
|
||||
|
||||
var objectPath = require('object-path');
|
||||
var exceptions = require('../../../src/lib/exceptions');
|
||||
var exceptions = require('../../../src/lib/Exceptions');
|
||||
|
||||
var UNAUTHORIZED_MESSAGE = 'Unauthorized access';
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import * as winston from "winston";
|
||||
import * as speakeasy from "speakeasy";
|
||||
import winston = require("winston");
|
||||
import speakeasy = require("speakeasy");
|
||||
import nodemailer = require("nodemailer");
|
||||
import session = require("express-session");
|
||||
import nedb = require("nedb");
|
||||
import ldapjs = require("ldapjs");
|
||||
|
||||
export type Nodemailer = typeof nodemailer;
|
||||
export type Speakeasy = typeof speakeasy;
|
||||
|
@ -18,10 +19,4 @@ export interface GlobalDependencies {
|
|||
winston: Winston;
|
||||
speakeasy: Speakeasy;
|
||||
nedb: Nedb;
|
||||
}
|
||||
|
||||
export type NodemailerDependencies = Nodemailer;
|
||||
|
||||
export interface NotifierDependencies {
|
||||
nodemailer: Nodemailer;
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
|
||||
import AuthenticationRegulator from "../../src/lib/AuthenticationRegulator";
|
||||
import UserDataStore from "../../src/lib/UserDataStore";
|
||||
import * as MockDate from "mockdate";
|
||||
|
||||
const exceptions = require("../../src/lib/exceptions");
|
||||
import MockDate = require("mockdate");
|
||||
import exceptions = require("../../src/lib/Exceptions");
|
||||
|
||||
describe("test authentication regulator", function() {
|
||||
it("should mark 2 authentication and regulate (resolve)", function() {
|
||||
|
|
8
test/unitary/mocks/AccessController.ts
Normal file
8
test/unitary/mocks/AccessController.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
import sinon = require("sinon");
|
||||
|
||||
export = function () {
|
||||
return {
|
||||
isDomainAllowedForUser: sinon.stub()
|
||||
};
|
||||
};
|
9
test/unitary/mocks/AuthenticationRegulator.ts
Normal file
9
test/unitary/mocks/AuthenticationRegulator.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
import sinon = require("sinon");
|
||||
|
||||
export = function () {
|
||||
return {
|
||||
mark: sinon.stub(),
|
||||
regulate: sinon.stub()
|
||||
};
|
||||
};
|
10
test/unitary/mocks/Ldap.ts
Normal file
10
test/unitary/mocks/Ldap.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
import sinon = require("sinon");
|
||||
|
||||
export = function () {
|
||||
return {
|
||||
bind: sinon.stub(),
|
||||
get_emails: sinon.stub(),
|
||||
get_groups: sinon.stub()
|
||||
};
|
||||
};
|
11
test/unitary/mocks/express.ts
Normal file
11
test/unitary/mocks/express.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
import sinon = require("sinon");
|
||||
|
||||
export = {
|
||||
Response: function () {
|
||||
return {
|
||||
send: sinon.stub(),
|
||||
status: sinon.stub()
|
||||
};
|
||||
}
|
||||
};
|
|
@ -9,14 +9,10 @@ import { NotifierFactory } from "../../../src/lib/notifiers/NotifierFactory";
|
|||
import { GMailNotifier } from "../../../src/lib/notifiers/GMailNotifier";
|
||||
import { FileSystemNotifier } from "../../../src/lib/notifiers/FileSystemNotifier";
|
||||
|
||||
import { NotifierDependencies } from "../../../src/types/Dependencies";
|
||||
import nodemailerMock = require("../mocks/nodemailer");
|
||||
|
||||
|
||||
describe("test notifier", function() {
|
||||
const deps: NotifierDependencies = {
|
||||
nodemailer: NodemailerMock
|
||||
};
|
||||
|
||||
describe("test notifier factory", function() {
|
||||
it("should build a Gmail Notifier", function() {
|
||||
const options = {
|
||||
gmail: {
|
||||
|
@ -24,7 +20,8 @@ describe("test notifier", function() {
|
|||
password: "password"
|
||||
}
|
||||
};
|
||||
assert(NotifierFactory.build(options, deps) instanceof GMailNotifier);
|
||||
nodemailerMock.createTransport.returns(sinon.spy());
|
||||
assert(NotifierFactory.build(options, nodemailerMock) instanceof GMailNotifier);
|
||||
});
|
||||
|
||||
it("should build a FS Notifier", function() {
|
||||
|
@ -34,6 +31,6 @@ describe("test notifier", function() {
|
|||
}
|
||||
};
|
||||
|
||||
assert(NotifierFactory.build(options, deps) instanceof FileSystemNotifier);
|
||||
assert(NotifierFactory.build(options, nodemailerMock) instanceof FileSystemNotifier);
|
||||
});
|
||||
});
|
||||
|
|
136
test/unitary/routes/FirstFactor.test.ts
Normal file
136
test/unitary/routes/FirstFactor.test.ts
Normal file
|
@ -0,0 +1,136 @@
|
|||
|
||||
import sinon = require("sinon");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import assert = require("assert");
|
||||
import winston = require("winston");
|
||||
|
||||
import FirstFactor = require("../../../src/lib/routes/FirstFactor");
|
||||
import exceptions = require("../../../src/lib/Exceptions");
|
||||
import AuthenticationRegulatorMock = require("../mocks/AuthenticationRegulator");
|
||||
import AccessControllerMock = require("../mocks/AccessController");
|
||||
import LdapMock = require("../mocks/Ldap");
|
||||
import ExpressMock = require("../mocks/express");
|
||||
|
||||
describe("test the first factor validation route", function() {
|
||||
let req: any;
|
||||
let res: any;
|
||||
let emails: string[];
|
||||
let groups: string[];
|
||||
let configuration;
|
||||
let ldapMock: any;
|
||||
let regulator: any;
|
||||
let accessController: any;
|
||||
|
||||
beforeEach(function() {
|
||||
configuration = {
|
||||
ldap: {
|
||||
base_dn: "ou=users,dc=example,dc=com",
|
||||
user_name_attribute: "uid"
|
||||
}
|
||||
};
|
||||
|
||||
emails = [ "test_ok@example.com" ];
|
||||
groups = [ "group1", "group2" ];
|
||||
|
||||
ldapMock = LdapMock();
|
||||
|
||||
accessController = AccessControllerMock();
|
||||
accessController.isDomainAllowedForUser.returns(true);
|
||||
|
||||
regulator = AuthenticationRegulatorMock();
|
||||
regulator.regulate.returns(BluebirdPromise.resolve());
|
||||
regulator.mark.returns(BluebirdPromise.resolve());
|
||||
|
||||
const app_get = sinon.stub();
|
||||
app_get.withArgs("ldap").returns(ldapMock);
|
||||
app_get.withArgs("configuration").returns(configuration);
|
||||
app_get.withArgs("logger").returns(winston);
|
||||
app_get.withArgs("authentication regulator").returns(regulator);
|
||||
app_get.withArgs("access controller").returns(accessController);
|
||||
|
||||
req = {
|
||||
app: {
|
||||
get: app_get
|
||||
},
|
||||
body: {
|
||||
username: "username",
|
||||
password: "password"
|
||||
},
|
||||
session: {
|
||||
auth_session: {
|
||||
FirstFactor: false,
|
||||
second_factor: false
|
||||
}
|
||||
}
|
||||
};
|
||||
res = ExpressMock.Response();
|
||||
});
|
||||
|
||||
it("should return status code 204 when LDAP binding succeeds", function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
res.send = sinon.spy(function() {
|
||||
assert.equal("username", req.session.auth_session.userid);
|
||||
assert.equal(204, res.status.getCall(0).args[0]);
|
||||
resolve();
|
||||
});
|
||||
ldapMock.bind.withArgs("username").returns(BluebirdPromise.resolve());
|
||||
ldapMock.get_emails.returns(BluebirdPromise.resolve(emails));
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
it("should retrieve email from LDAP", function(done) {
|
||||
res.send = sinon.spy(function() { done(); });
|
||||
ldapMock.bind.returns(BluebirdPromise.resolve());
|
||||
ldapMock.get_emails = sinon.stub().withArgs("usernam").returns(BluebirdPromise.resolve([{mail: ["test@example.com"] }]));
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
|
||||
it("should set email as session variables", function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
res.send = sinon.spy(function() {
|
||||
assert.equal("test_ok@example.com", req.session.auth_session.email);
|
||||
resolve();
|
||||
});
|
||||
const emails = [ "test_ok@example.com" ];
|
||||
ldapMock.bind.returns(BluebirdPromise.resolve());
|
||||
ldapMock.get_emails.returns(BluebirdPromise.resolve(emails));
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
it("should return status code 401 when LDAP binding throws", function(done) {
|
||||
res.send = sinon.spy(function() {
|
||||
assert.equal(401, res.status.getCall(0).args[0]);
|
||||
assert.equal(regulator.mark.getCall(0).args[0], "username");
|
||||
done();
|
||||
});
|
||||
ldapMock.bind.throws(new exceptions.LdapBindError("Bad credentials"));
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
|
||||
it("should return status code 500 when LDAP search throws", function(done) {
|
||||
res.send = sinon.spy(function() {
|
||||
assert.equal(500, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
ldapMock.bind.returns(BluebirdPromise.resolve());
|
||||
ldapMock.get_emails.throws(new exceptions.LdapSeachError("error while retrieving emails"));
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
|
||||
it("should return status code 403 when regulator rejects authentication", function(done) {
|
||||
const err = new exceptions.AuthenticationRegulationError("Authentication regulation...");
|
||||
regulator.regulate.returns(BluebirdPromise.reject(err));
|
||||
|
||||
res.send = sinon.spy(function() {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
ldapMock.bind.returns(BluebirdPromise.resolve());
|
||||
ldapMock.get_emails.returns(BluebirdPromise.resolve());
|
||||
FirstFactor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
|
||||
var sinon = require('sinon');
|
||||
var Promise = require('bluebird');
|
||||
var assert = require('assert');
|
||||
var winston = require('winston');
|
||||
var first_factor = require('../../../src/lib/routes/first_factor');
|
||||
var exceptions = require('../../../src/lib/exceptions');
|
||||
var Ldap = require('../../../src/lib/ldap');
|
||||
|
||||
describe('test the first factor validation route', function() {
|
||||
var req, res;
|
||||
var ldap_interface_mock;
|
||||
var emails;
|
||||
var search_res_ok;
|
||||
var regulator;
|
||||
var access_controller;
|
||||
var config;
|
||||
|
||||
beforeEach(function() {
|
||||
ldap_interface_mock = sinon.createStubInstance(Ldap);
|
||||
config = {
|
||||
ldap: {
|
||||
base_dn: 'ou=users,dc=example,dc=com',
|
||||
user_name_attribute: 'uid'
|
||||
}
|
||||
}
|
||||
|
||||
emails = [ 'test_ok@example.com' ];
|
||||
groups = [ 'group1', 'group2' ];
|
||||
|
||||
regulator = {};
|
||||
regulator.mark = sinon.stub();
|
||||
regulator.regulate = sinon.stub();
|
||||
|
||||
regulator.mark.returns(Promise.resolve());
|
||||
regulator.regulate.returns(Promise.resolve());
|
||||
|
||||
access_controller = {
|
||||
isDomainAllowedForUser: sinon.stub().returns(true)
|
||||
};
|
||||
|
||||
var app_get = sinon.stub();
|
||||
app_get.withArgs('ldap').returns(ldap_interface_mock);
|
||||
app_get.withArgs('config').returns(config);
|
||||
app_get.withArgs('logger').returns(winston);
|
||||
app_get.withArgs('authentication regulator').returns(regulator);
|
||||
app_get.withArgs('access controller').returns(access_controller);
|
||||
|
||||
req = {
|
||||
app: {
|
||||
get: app_get
|
||||
},
|
||||
body: {
|
||||
username: 'username',
|
||||
password: 'password'
|
||||
},
|
||||
session: {
|
||||
auth_session: {
|
||||
first_factor: false,
|
||||
second_factor: false
|
||||
}
|
||||
}
|
||||
}
|
||||
res = {
|
||||
send: sinon.spy(),
|
||||
status: sinon.spy()
|
||||
}
|
||||
});
|
||||
|
||||
it('should return status code 204 when LDAP binding succeeds', function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
res.send = sinon.spy(function(data) {
|
||||
assert.equal('username', req.session.auth_session.userid);
|
||||
assert.equal(204, res.status.getCall(0).args[0]);
|
||||
resolve();
|
||||
});
|
||||
ldap_interface_mock.bind.withArgs('username').returns(Promise.resolve());
|
||||
ldap_interface_mock.get_emails.returns(Promise.resolve(emails));
|
||||
first_factor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
it('should retrieve email from LDAP', function(done) {
|
||||
res.send = sinon.spy(function(data) { done(); });
|
||||
ldap_interface_mock.bind.returns(Promise.resolve());
|
||||
ldap_interface_mock.get_emails = sinon.stub().withArgs('usernam').returns(Promise.resolve([{mail: ['test@example.com'] }]));
|
||||
first_factor(req, res);
|
||||
});
|
||||
|
||||
it('should set email as session variables', function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
res.send = sinon.spy(function(data) {
|
||||
assert.equal('test_ok@example.com', req.session.auth_session.email);
|
||||
resolve();
|
||||
});
|
||||
var emails = [ 'test_ok@example.com' ];
|
||||
ldap_interface_mock.bind.returns(Promise.resolve());
|
||||
ldap_interface_mock.get_emails.returns(Promise.resolve(emails));
|
||||
first_factor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return status code 401 when LDAP binding throws', function(done) {
|
||||
res.send = sinon.spy(function(data) {
|
||||
assert.equal(401, res.status.getCall(0).args[0]);
|
||||
assert.equal(regulator.mark.getCall(0).args[0], 'username');
|
||||
done();
|
||||
});
|
||||
ldap_interface_mock.bind.throws(new exceptions.LdapBindError('Bad credentials'));
|
||||
first_factor(req, res);
|
||||
});
|
||||
|
||||
it('should return status code 500 when LDAP search throws', function(done) {
|
||||
res.send = sinon.spy(function(data) {
|
||||
assert.equal(500, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
ldap_interface_mock.bind.returns(Promise.resolve());
|
||||
ldap_interface_mock.get_emails.throws(new exceptions.LdapSearchError('err'));
|
||||
first_factor(req, res);
|
||||
});
|
||||
|
||||
it('should return status code 403 when regulator rejects authentication', function(done) {
|
||||
var err = new exceptions.AuthenticationRegulationError();
|
||||
regulator.regulate.returns(Promise.reject(err));
|
||||
res.send = sinon.spy(function(data) {
|
||||
assert.equal(403, res.status.getCall(0).args[0]);
|
||||
done();
|
||||
});
|
||||
ldap_interface_mock.bind.returns(Promise.resolve());
|
||||
ldap_interface_mock.get_emails.returns(Promise.resolve());
|
||||
first_factor(req, res);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
var sinon = require('sinon');
|
||||
var identity_check = require('../../src/lib/identity_check');
|
||||
var exceptions = require('../../src/lib/exceptions');
|
||||
var exceptions = require('../../src/lib/Exceptions');
|
||||
var assert = require('assert');
|
||||
var winston = require('winston');
|
||||
var Promise = require('bluebird');
|
||||
|
|
|
@ -122,7 +122,7 @@ describe('test ldap validation', function() {
|
|||
var expected_doc = {};
|
||||
expected_doc.mail = [];
|
||||
expected_doc.mail.push('user@example.com');
|
||||
ldap_client.search.yields('error');
|
||||
ldap_client.search.yields('Error while searching mails');
|
||||
|
||||
return ldap.get_emails('user')
|
||||
.catch(function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user