node-ldapjs icon indicating copy to clipboard operation
node-ldapjs copied to clipboard

How to use client.starttls()

Open lukelafountaine opened this issue 9 years ago • 10 comments

I am having a little trouble figuring out how to use the client starttls() function. I am creating the client this way:

client = ldap.createClient({
    url: config.ldap.url
});

The client is created correctly and upon calling the starttls function as

client.starttls({}, function(err) {
    console.log('inside the starttls's callback');
});

However, the callback function never gets called. I get the error : [TypeError: Object.keys called on non-object]. In the Node.js TLS documentation it mentions that on connecting, if the certificate authority is left blank it will default to the system certificates, and I was assuming that this would act in the same way. If there were any thoughts on what is going wrong here, that would be great.

lukelafountaine avatar Dec 07 '15 21:12 lukelafountaine

Please post the full stacktrace from the error.

pfmooney avatar Dec 08 '15 01:12 pfmooney

Please look at issue #307 It might help you solve the problem

aneelaSaleem avatar Dec 08 '15 19:12 aneelaSaleem

@aneelaSaleem It does not appear that this issue has anything to do with the difficulties you experienced in #307. Please do not post references to tickets unless you know them to be related.

pfmooney avatar Dec 08 '15 21:12 pfmooney

Sorry for the delay. I haven't been working on this for this past week. Here is the stack trace:

TypeError: Object.keys called on non-object
      at Function.keys (native)
      at wrapper (/usr/src/app/node_modules/ldapjs/node_modules/once/node_modules/wrappy/wrappy.js:27:14)
      at Client.starttls (/usr/src/app/node_modules/ldapjs/lib/client/client.js:880:14)
      at AuthenticationHelper.validateToken (/usr/src/app/helpers/authentication.js:97:12)
      at Server.AuthenticationCheck.checkAuth (/usr/src/app/middlewares/authenticationCheck.js:25:14)
      at next (/usr/src/app/node_modules/restify/lib/server.js:906:30)
      at f (/usr/src/app/node_modules/restify/node_modules/once/once.js:17:25)
      at b (domain.js:183:18)
      at Domain.run (domain.js:123:23)
      at Server._run (/usr/src/app/node_modules/restify/lib/server.js:959:7)
      at Server._handle (/usr/src/app/node_modules/restify/lib/server.js:719:14)
      at Server.onRequest (/usr/src/app/node_modules/restify/lib/server.js:326:14)
      at Server.emit (events.js:98:17)
      at HTTPParser.parser.onIncoming (http.js:2109:12)
      at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:122:23)
      at CleartextStream.socket.ondata (http.js:1967:22)

After some further looking, it appears that the controls parameter is required. I was leaving that out as optional, so it was trying to use the callback as the controls. After that, I passed in an empty object for the controls, and apparently it requires the controls to be an array so passing in an empty array works. That might be something helpful to have in the docs or have some type checking on the controls.

lukelafountaine avatar Dec 14 '15 17:12 lukelafountaine

Yeah, the non-optional controls parameter was an oversight in the implementation and needs to be fixed.

pfmooney avatar Jan 10 '16 18:01 pfmooney

Please update the documentation as well that controls parameter is not optional.

ghost avatar Jul 04 '17 06:07 ghost

Just ran into this too -- it'd be nice to know controls aren't optional, when the examples omit it.

martinb3 avatar Oct 23 '17 15:10 martinb3

What are the "controls" supposed to be? The documentation just says starttls(options, controls, callback).

But in the example there are no controls present, just options and callback: client.starttls(opts, function(err, res) { });

woutrbe avatar Apr 16 '18 02:04 woutrbe

Just ran into the same issue and this helped me: var controls = client.controls;

Complete example:

import LDAP from 'ldapjs';

var opts = {
    ca: [fs.readFileSync('./server/ldap.pem')],
    host: 'example.com',
    reconnect: true,
    rejectUnauthorized: false // for self-signed
};

var client = LDAP.createClient({
    url: protocol + host + ":" + ldapport,
    tlsOptions: opts
});

var controls = client.controls;

client.starttls(opts, controls, function(err, res) {
    assert.ifError(err);
    client.bind(dn, password, function (err) {
        assert.ifError(err);
    });
    log.info("StartTTLS connection established.")
  });

kohleman avatar Oct 04 '18 13:10 kohleman

@kohleman could you please tell what protocol and ldapport you are using?

siddjain avatar Apr 17 '19 21:04 siddjain

I also ran into this. As a workaround I have set the controls parameter to an empty array:

client.starttls(opts, [], function(err, res) { ... })

Which is basically what the other methods do when no controls are provided (and also what #651 offers).

fengtan avatar Nov 28 '22 04:11 fengtan

👋

On February 22, 2023, we released version 3 of this library. As a result, we are closing this issue/pull request.

Please see issue #839 for more information, including how to proceed if you feel this closure is in error.

jsumners avatar Feb 22 '23 19:02 jsumners