var util = require('util') var ldap = require('ldapjs') var Promise = require('bluebird') function InvalidCredentialsError(user) { Error.call(this, util.format('Invalid credentials for user "%s"', user)) this.name = 'InvalidCredentialsError' this.user = user Error.captureStackTrace(this, InvalidCredentialsError) } util.inherits(InvalidCredentialsError, Error) // Export module.exports.InvalidCredentialsError = InvalidCredentialsError // Export module.exports.login = function(options, username, password) { function tryConnect() { var resolver = Promise.defer() var client = ldap.createClient({ url: options.url , timeout: options.timeout , maxConnections: 1 }) if (options.bind.dn) { client.bind(options.bind.dn, options.bind.credentials, function(err) { if (err) { resolver.reject(err) } else { resolver.resolve(client) } }) } else { resolver.resolve(client) } return resolver.promise } function tryFind(client) { var resolver = Promise.defer() var query = { scope: options.search.scope , filter: new ldap.AndFilter({ filters: [ new ldap.EqualityFilter({ attribute: 'objectClass' , value: options.search.objectClass }) , new ldap.EqualityFilter({ attribute: options.search.field , value: username }) ] }) } client.search(options.search.dn, query, function(err, search) { if (err) { return resolver.reject(err) } function entryListener(entry) { resolver.resolve(entry) } function endListener() { resolver.reject(new InvalidCredentialsError(username)) } function errorListener(err) { resolver.reject(err) } search.on('searchEntry', entryListener) search.on('end', endListener) search.on('error', errorListener) resolver.promise.finally(function() { search.removeListener('searchEntry', entryListener) search.removeListener('end', endListener) search.removeListener('error', errorListener) }) }) return resolver.promise } function tryBind(client, entry) { return new Promise(function(resolve, reject) { client.bind(entry.object.dn, password, function(err) { if (err) { reject(new InvalidCredentialsError(username)) } else { resolve(entry.object) } }) }) } return tryConnect().then(function(client) { return tryFind(client) .then(function(entry) { return tryBind(client, entry) }) .finally(function() { client.unbind() }) }) } // Export module.exports.email = function(user) { return user.mail || user.email || user.userPrincipalName }