vesse / node-ldapauth-fork

Simple node.js module to authenticate against an LDAP server
Other
127 stars 79 forks source link

Connects anonymously after losing server connection #67

Closed theasp closed 5 years ago

theasp commented 6 years ago

I'm having a problem with authentication not working after my LDAP connection is lost. It's successfully reconnecting, but not binding to the admin user, which prevents logins.

After restarting the LDAP server:

{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","level":10,"msg":"end event","time":"2018-10-05T01:55:09.544Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"2__ldaps://my.ldap.server","level":10,"msg":"close event had_err=no","time":"2018-10-05T01:55:09.544Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","level":10,"msg":"end event","time":"2018-10-05T01:55:09.545Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"1__ldaps://my.ldap.server","level":10,"msg":"close event had_err=no","time":"2018-10-05T01:55:09.545Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"3__ldaps://my.ldap.server","level":20,"msg":"connected after 5 attempt(s)","time":"2018-10-05T01:55:40.845Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"4__ldaps://my.ldap.server","level":20,"msg":"connected after 5 attempt(s)","time":"2018-10-05T01:55:40.850Z","v":0}

On the next login attempt:

{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"4__ldaps://my.ldap.server","level":10,"msg":"sending request {\"messageID\":1,\"protocolOp\":\"SearchRequest\",\"baseObject\":{\"rdns\":[{\"attrs\":{\"cn\":{\"value\":\"users\",\"name\":\"cn\",\"order\":0}},\"spLead\":0,\"spTrail\":0},{\"attrs\":{\"cn\":{\"value\":\"accounts\",\"name\":\"cn\",\"order\":0}},\"spLead\":0,\"spTrail\":0},{\"attrs\":{\"dc\":{\"value\":\"xxx\",\"name\":\"dc\",\"order\":0}},\"spLead\":0,\"spTrail\":0},{\"attrs\":{\"dc\":{\"value\":\"ca\",\"name\":\"dc\",\"order\":0}},\"spLead\":0,\"spTrail\":0}],\"_format\":{}},\"scope\":\"sub\",\"derefAliases\":0,\"sizeLimit\":0,\"timeLimit\":10,\"typesOnly\":false,\"filter\":\"(uid=myuser)\",\"attributes\":[],\"controls\":[]}","time":"2018-10-05T01:58:16.069Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"1__ldaps://my.ldap.server","level":10,"msg":"data event: <Buffer 30 2c 02 01 01 65 27 0a 01 30 04 00 04 20 41 6e 6f 6e 79 6d 6f 75 73 20 61 63 63 65 73 73 20 69 73 20 6e 6f 74 20 61 6c 6c 6f 77 65 64 2e>","time":"2018-10-05T01:58:16.108Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"1__ldaps://my.ldap.server","level":10,"msg":"parse: data=<Buffer 0a 01 30 04 00 04 20 41 6e 6f 6e 79 6d 6f 75 73 20 61 63 63 65 73 73 20 69 73 20 6e 6f 74 20 61 6c 6c 6f 77 65 64 2e>","time":"2018-10-05T01:58:16.109Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"1__ldaps://my.ldap.server","level":10,"msg":"Parsing done: {\"messageID\":1,\"protocolOp\":\"LDAPResult\",\"status\":48,\"matchedDN\":\"\",\"errorMessage\":\"Anonymous access is not allowed.\",\"referrals\":[],\"controls\":[]}","time":"2018-10-05T01:58:16.109Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"clazz":"Client","ldap_id":"4__ldaps://my.ldap.server","level":10,"msg":"response received","time":"2018-10-05T01:58:16.109Z","v":0}
{"name":"lapidary","hostname":"mybox","pid":724,"component":"ldapauth","level":10,"msg":"ldap authenticate: user search error: 48 InappropriateAuthenticationError Anonymous access is not allowed.","time":"2018-10-05T01:58:16.110Z","v":0}

For reconnect in options, I'm using initialDelay of 5000 and maxDelay of 60000.

vesse commented 6 years ago

Hmm it should reset the adminBound flag in case of errors but maybe it's not then working as expected. Unfortunately I don't have much time to look at this, but the strategy implementation is quite simple, maybe you could debug it a little further?

theasp commented 6 years ago

It doesn't appear the error event is ever fired. From this issue, https://github.com/joyent/node-ldapjs/issues/392, it appears that this is expected. Near the end there is an example to handle it is by binding using the connect event:

    // e.g. in your client's class constructor

    this.ldapClient = ldap.createClient({
        url: ldap_url,
        reconnect: {
            initialDelay: 100,
            maxDelay: 1000,
            failAfter: 10
        }
    });

    const client = this.ldapClient;
    // do a rebind when reconnect
    this.ldapClient.on('connect', function () {
        client.bind(ldap_user, ldap_pwd, err => {
            if (err) {
                logger.error('error while ldap binding' + err);
            }
        });
    });

PR incoming...

theasp commented 5 years ago

68 resolves this.