From d52b49c10516ac5b6fb3d584503f2f863326834d Mon Sep 17 00:00:00 2001 From: Fabian Jucker Date: Tue, 16 Jul 2019 09:16:10 +0200 Subject: [PATCH] create new ldap connection per request (fixes #27) --- src/app.js | 9 ++++++--- src/ldap/client.js | 25 ++++++++++++++++--------- test/unit/ldap/client.test.js | 17 ++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/app.js b/src/app.js index 21210e0..0f48205 100644 --- a/src/app.js +++ b/src/app.js @@ -13,12 +13,15 @@ import {Client, Authenticator, Mapping} from './ldap'; import {Healthz, UserAuthentication, TokenAuthentication} from './api'; // setup basic dependencies -let ldapClient = new Client( - new Connection({ +const connectionFactory = () => { + return new Connection({ url: config.ldap.uri, timeout: config.ldap.timeout * 1000, connectTimeout: config.ldap.timeout * 1000, - }), + }); +}; +let ldapClient = new Client( + connectionFactory, config.ldap.baseDn, config.ldap.bindDn, config.ldap.bindPw, diff --git a/src/ldap/client.js b/src/ldap/client.js index 5409a2b..f1dec7c 100644 --- a/src/ldap/client.js +++ b/src/ldap/client.js @@ -1,20 +1,25 @@ // @flow /** Class for an LDAP client */ export default class Client { - client: Object; + clientFactory: () => Object; basedn: string; binddn: string; bindpw: string; /** * Create an LDAP client. - * @param {Object} conn - Ldap connection. + * @param {Function} connectionFactory - Ldap connection factory. * @param {string} basedn - The base DN to use. * @param {string} binddn - DN of the bind user to use. * @param {string} bindpw - Password of the bind user to use. */ - constructor(conn: Object, basedn: string, binddn: string, bindpw: string) { - this.client = conn; + constructor( + connectionFactory: () => Object, + basedn: string, + binddn: string, + bindpw: string + ) { + this.clientFactory = connectionFactory; this.basedn = basedn; this.binddn = binddn; this.bindpw = bindpw; @@ -27,14 +32,15 @@ export default class Client { * @return {Promise} */ async bind(dn: string, password: string): Promise { + let client = this.clientFactory(); let authenticated = false; try { - await this.client.bind(dn, password, []); + await client.bind(dn, password, []); authenticated = true; } catch (error) { authenticated = false; } finally { - await this.client.unbind(); + await client.unbind(); } return authenticated; } @@ -51,23 +57,24 @@ export default class Client { attributes: ?Array, basedn: ?string ): Promise { + let client = this.clientFactory(); if (!basedn) { basedn = this.basedn; } let searchResult = null; try { - await this.client.bind(this.binddn, this.bindpw, []); + await client.bind(this.binddn, this.bindpw, []); const options = { filter: filter, scope: 'sub', attributes: attributes, }; - searchResult = await this.client.search(basedn, options, []); + searchResult = await client.search(basedn, options, []); } catch (error) { throw error; } finally { - await this.client.unbind(); + await client.unbind(); } if (searchResult && searchResult.searchEntries.length > 0) { return searchResult.searchEntries[0]; diff --git a/test/unit/ldap/client.test.js b/test/unit/ldap/client.test.js index 7e8a0f6..ee4a6fe 100644 --- a/test/unit/ldap/client.test.js +++ b/test/unit/ldap/client.test.js @@ -19,16 +19,12 @@ const fixtures = { }; let connection = new Connection(); +let connectionFactory = () => { + return connection; +}; let client = null; beforeEach(() => { - client = new Client( - connection, - fixtures.basedn, - fixtures.binddn, - fixtures.bindpw, - true - ); connection.starttlsReturnsError = false; connection.bindReturnsError = false; connection.searchReturnsError = false; @@ -39,6 +35,13 @@ beforeEach(() => { uid: fixtures.username, memberOf: fixtures.groups, }; + client = new Client( + connectionFactory, + fixtures.basedn, + fixtures.binddn, + fixtures.bindpw, + true + ); }); describe('Client.bind()', () => {