vesse / node-ldapauth-fork Goto Github PK
View Code? Open in Web Editor NEWThis project forked from trentm/node-ldapauth
Simple node.js module to authenticate against an LDAP server
License: Other
This project forked from trentm/node-ldapauth
Simple node.js module to authenticate against an LDAP server
License: Other
My bind (admin) user and the users that I actually want to authenticate have different search bases. The only parts they have in common are the dc
parts. If I set a search base that's sufficient to find my bind user, it will never find my regular users. Does that make sense?
So, for example, I have a bind user with DN like: DN=admin,OU=admins,OU=specialUsers,DC=example,DC=com
And regular users who I want to authenticate like: DN=JoeBlow,OU=chumps,OU=regularDudes,DC=example,DC=com
Then I can set bindDN
to that first string (actually, just admin would be enough) and set the searchBase to something like: OU=specialUsers,DC=example,DC=com
and the bind user will be authenticated properly but JoeBlow will not be able to log in because the searchBase misses him.
Any suggestion?
as explained @ trentm#13 (comment)
you should wrap the bcrypt
calls with try { ... } catch( err ) { ... }
or move the bcrypt
back to normal dependencies...
The documentation says:
Admin connection DN, e.g. uid=myapp,ou=users,dc=example,dc=org
. Optional. If not given at all, admin client is not bound. Giving empty string may result in anonymous bind when allowed.
I tried both removing the option bindDn and using empty string but I am getting following response.
Error: { OperationsError: 000004DC: LdapErr: DSID-0C0907C2, comment: In order to perform this operation a successful bind must be completed on the connection.,
#20
#26
vesse/passport-ldapauth#38
We found another error case that isn't bubbling up properly through the err
parameter to the callback. When the search filter is syntactically incorrect, an example call stack looks like this:
Error: ([email protected] has unbalanced parentheses
at matchParens (...\node_modules\ldap-filter\lib\index.js:49:11)
at _buildFilterTree (...\node_modules\ldap-filter\lib\index.js:155:18)
at _parseString (...\node_modules\ldap-filter\lib\index.js:411:17)
at Object.module.exports.parse (...\node_modules\ldap-filter\lib\index.js:422:12)
at Object.parseString (...\node_modules\ldapjs\lib\filters\index.js:176:25)
at Client.search (...\node_modules\ldapjs\lib\client\client.js:769:30)
at ...\node_modules\ldapauth-fork\lib\ldapauth.js:197:23
at ...\node_modules\ldapauth-fork\lib\ldapauth.js:178:12
ldap-filter is throwing when the filter parser detects syntax errors.
Ultimately, it seems like this library needs to just change to be, overall, more resilient to errors lower in the stack of its interactions with the lower-level LDAP modules. This issue, in our case, affects us through our use of vesse/passport-ldapauth.
Do you have any plans to address these error handling issues that keep cropping up in different flavors?
In ldapauth.d.ts the class LdapAuth isn't part of the namespace LdapAuth and isn't exported.
Moving the class to the namespace seems to fix this.
would it be possible to change the dependency to becryptjs?
it is compatible to bcrypt, but does not have those aweful c++ dependencies
I got this stack trace
[2017-05-30 04:58:49.312] [ERROR] [default] - Error: This socket is closed
at Socket._writeGeneric (net.js:683:19)
at Socket._write (net.js:734:8)
at doWrite (_stream_writable.js:334:12)
at writeOrBuffer (_stream_writable.js:320:5)
at Socket.Writable.write (_stream_writable.js:247:11)
at Socket.write (net.js:661:40)
at Client._send (/usr/local/cdt/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:914:17)
at Client.bind (/usr/local/cdt/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:367:15)
at LdapAuth._adminBind (/usr/local/cdt/node_modules/ldapauth-fork/lib/ldapauth.js:171:21)
at LdapAuth._search (/usr/local/cdt/node_modules/ldapauth-fork/lib/ldapauth.js:193:8)
at LdapAuth._findUser (/usr/local/cdt/node_modules/ldapauth-fork/lib/ldapauth.js:253:8)
at module.exports (/usr/local/cdt/middleware/auth.js:184:8)
at Layer.handle [as handle_request] (/usr/local/cdt/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/local/cdt/node_modules/express/lib/router/index.js:312:13)
at /usr/local/cdt/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/usr/local/cdt/node_modules/express/lib/router/index.js:330:12)
at next (/usr/local/cdt/node_modules/express/lib/router/index.js:271:10)
at /usr/local/cdt/app.js:66:5
at Layer.handle [as handle_request] (/usr/local/cdt/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/local/cdt/node_modules/express/lib/router/index.js:312:13)
at /usr/local/cdt/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/usr/local/cdt/node_modules/express/lib/router/index.js:330:12)
at next (/usr/local/cdt/node_modules/express/lib/router/index.js:271:10)
at serveStatic (/usr/local/cdt/node_modules/serve-static/index.js:75:16)
at Layer.handle [as handle_request] (/usr/local/cdt/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/local/cdt/node_modules/express/lib/router/index.js:312:13)
at /usr/local/cdt/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/usr/local/cdt/node_modules/express/lib/router/index.js:330:12)
I am hoping to listen for errors or close events like so:
let ldap = new LdapAuth(config.ldap);
ldap.once('error', foo);
ldap.once('close', bar);
but apparently the ldap instance is not an event emitter. How can I listen for errors etc?
The LDAP server I'm using tends to, for reasons I'm not privy to, reset its connection to my node.js application.
This results in an uncaught error that causes node to exit:
Uncaught Error: read ECONNRESET
FROM
Client.emit (events.js:160:7)
Socket.onSocketError (/var/www/html/node_modules/ldapjs/lib/client/client.js:1169:12)
emitOne (events.js:96:13)
Socket.emit (events.js:188:7)
emitErrorNT (net.js:1272:8)
_combinedTickCallback (internal/process/next_tick.js:74:11)
process._tickCallback (internal/process/next_tick.js:98:9)
I am using ldapauth-fork as described in issue #38
I understand that the uncaught exception is thrown because there is no listener for the 'error' event - but the event fires on 'Client'. I'd be grateful for any advice as to how to catch this error properly (it occurs every 5-10 mins).
Currently, I am relying on pm2 to restart node.
connect no longer has a basicAuth method, because I believe they moved all middleware outside.
This mean that the example is broken.
Could it be fixed?
I'm asking because it took me a long time to figure out how to fix it, I ended up with the following middleware to support basic authentication via LDAP:
const basicAuth = require('basic-auth');
const basicAuthenticator = (req, res, next) => {
function reject() {
res.statusCode = 401
res.setHeader('WWW-Authenticate', 'Basic realm="please use your SLO"')
res.end('Access denied')
}
var credentials = basicAuth(req)
if (!credentials) return reject();
ldap.authenticate(credentials.name, credentials.pass, function (err, user) {
if (err) return reject();
req.user = credentials.name;
next();
});
}
which I am not certain of, quite frankly, whether it handles all errors correctly.
Thank you!
When I first launch the node server, the ldap authentication works just fine. After it has been up for a little while, the ldap.authenticate() call starts to hang and then eventually returns a 502. I also can't figure out how to get more information on this, like a log or something.
So in my environment, I can authenticate anonymously with the LDAP server, however, the password is an empty string. When setting bindCredentials
to ''
, I get an error that indicates that the credentials are not a string.
bindCredentials: opts.bindCredentials || opts.Credentials || opts.adminPassword,
Since an empty string is falsy, it gets passed over, and eventually bindCredentials ends up being undefined
because the adminPassword
is not set.
So, the work around is to set adminPassword
to an empty string instead, however this code ought to know the difference between empty strings and undefined.
Hi, I've had a hard time getting up and running with this package, this particular error has been very unhelpful AssertionError: undefined == true
. I get that when I call new LdapAuth(options)
when options doesn't contain certain properties.
Could you please throw a more descriptive error?
I hope your still maintaining this and can answer my question.
i keep getting the same invalidCredentialsError no matter what credentials i have been putting in, i know the credentials i am using are correct does it not traverse the directories properly?
LdapAuth = require('ldapauth-fork');
var options = {
url: "ldap://10.213.200.5",
bindDn: "uid=adminuser, ou=company, o=directory",
bindCredentials: "password",
searchBase: "ou=company, o=directory",
searchFilter: "(uid={{username}})"
};
var auth = new LdapAuth(options);
var ldapValidate = function (username, password, callback){
console.log(username + " " + password);
auth.authenticate(username, password, function(err, user){
if(err){
console.log("an error occured while authenticating");
console.log(err);
}else{
console.log(user);
}
callback(err, user);
});
};
server.auth.strategy('psit-auth', 'basic', {validateFunc: ldapValidate });
Any chance this PR could be merged into this project? This is to resolve close
not working on Node 10
Thank you!
I am trying to connect ldap server using your library. The problem is i get the following error :
LDAP auth error: InvalidCredentialsError: 80090308: LdapErr: DSID-0C0903D0, comment: AcceptSecurityContext error, data 52e, v2580
I am using ldapsearch and its connecting to the ldap server, here is my ldapsearch command :
ldapsearch -H "ldap://10.XX.XX.X:389" -x -D "test\user.test" -w "password" -b "DC=domain,DC=org" "(uid=john)"
SImilarly, When i use library to connect to the ldap server using :
var ldap = new LdapAuth({
url:"ldap://10.XX.XX.X:389",
bindDn: "test\user.test",
bindCredentials: "password",
searchBase: "DC=domain,DC=org",
searchFilter: "(uid=john)",
cache: false,
verbose : true
});
ldap.authenticate("username", "password", function (err, user) {
if (err) {
console.log("LDAP auth error: %s", err);
}
});
Please guide me through the issue i am facing.
Is it possible to get an option to not connect to the LDAP service automatically when the class is created?
I'm using dependency injection and creating the ldapauth class in the constructor of my service but it isn't always used and in those cases the connection doesn't close properly and it crashes my application.
Example use case:
const LdapAuth = require('ldapauth-fork');
class LDAPService {
constructor() {
this.ldap = new LdapAuth({
autoConnect: false // Default to true for backwards compatibility
});
}
authenticateLdap(username, password, callback) {
// This connect() method would need to be implemented
this.ldap.connect(function(err) {
if(err) callback(err);
this.ldap.authenticate(username,password, function(err, user) {
if(err) callback(err);
this.ldap.close(function(err) {
if(err) callback(err);
callback(null, user);
});
});
});
}
}
I just logged in to my application without using a password and learned that the authenticate
method doesn't require a password because it will just bind anonymously.
Is this really the intended behavior?
I can perform the check for an empty password myself, I was just wondering if this was missed somehow and others have the same security hole in their system.
when the user object shows up I am trying to save the jpegPhoto to a file for use as the profile pic. But I cannot figure out the format
I have tried (among many other things):
fs.writeFileSync(jpgPath, ldapUser.jpegPhoto);
And
var jpg = new Buffer(ldapUser.jpegPhoto, 'base64');
fs.writeFileSync(jpgPath, jpg);
And
var img64 = Buffer.from(user.jpegPhoto).toString('base64');
var foto = "<div><img src='data:image/jpeg;base64,"+img64+"'/></div>"
fs.appendFile('index.html', foto, function (err) {
if (err) throw err;
console.log('Saved!');
});
Thanks!
I noticed my application is including moment.js as indirect dependency and it's coming from ldapauth-fork package, I've read the code and didn't find a usage of moment in this repository, is this dependency needed? considering it's 370Kb it would be good to remove.
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.
I have this code:
let ldap;
try {
ldap = new LdapAuth(config.ldap);
} catch (err) {
console.error(err);
return cb(err);
}
/// some time later...
ldap.close(function(err){
// sometimes this doesn't get called
});
from my testing, it appears that the ldap.close()
call times out frequently, might there be a good reason for that? no idea why
This is probably more of a bug for ldapjs
than ldapauth-fork
but currently they are in a middle of a large refactor and may have fixed this issue. But I wanted to leave a note about it here in case some other people run into this problem.
ldapjs 0.7.1 returns before sockets are closed and remove events before sockets are closed.
If i set the connectTimeout
to 1
and spam the server eventually it'll crash returning Error: This socket is closed.
or something close to that.
My work around requires listening to the _userClient.socket
events error
or close
and using when
for a promise so it doesn't return before it should because the sockets aren't done closing when unbind's callback is called.
Sorry this is in coffeescript
self = this
return whenjs()
.then ->
if self._adminBound
return whenjs.promise (resolve, reject) ->
self._adminClient.socket.on 'error', (err) ->
reject(err)
self._adminClient.socket.on 'close', ->
resolve()
self._adminClient.unbind()
.then ->
return whenjs.promise (resolve, reject) ->
self._userClient.socket.on 'close', ->
resolve()
self._userClient.socket.on 'error', (err) ->
reject(err)
self._userClient.unbind()
.then ->
callback()
.otherwise (err) ->
callback(err)
Hi,
I try to connect and login through LDAP using the following code:
ldap_auth.authenticate(user.name, user.pass, function(err, ldap_user) {
logger.info("LDAP authentication will be checked for user: " + user.name);
if (ldap_user) {
logger.info(ldap_user);
req.session.authentication = 1;
return next();
} else {
logger.warn("LDAP authentication is not valid: " + user.name);
logger.warn(err);
req.session.authentication = 1;
return next();
}
});
And my configuration settings is like that:
ldap_options = {
url: ldap_url,
searchBase: 'cn=admins,ou=Groups,dc=local',
searchFilter: '(uid={{username}})',
verbose:true,
cache:true,
tlsOptions: {
ca: [ca_file_content]
}
};
However, whenever I try to login, I've got following error:
warn: Error: write after end
at writeAfterEnd (_stream_writable.js:167:12)
at TLSSocket.Writable.write (_stream_writable.js:214:5)
at TLSSocket.Socket.write (net.js:634:40)
at Client._send (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:914:17)
at Client.search (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:678:15)
at /var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/lib/ldapauth.js:196:23
at LdapAuth._adminBind (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/lib/ldapauth.js:165:12)
at LdapAuth._search (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/lib/ldapauth.js:192:8)
at LdapAuth._findUser (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/lib/ldapauth.js:252:8)
at LdapAuth.authenticate (/var/ums/umsRemoteAccessProxy/node_modules/ldapauth-fork/lib/ldapauth.js:308:8)
Actually, I try to re-initialize the ldap client per each request; however, it gives another error: LDAP connection closed. I'm stuck currently. Do you have any idea about that?
We have different organizations to get our users from the ldap. To get them from there, we need the option to give over a empty search base query, because our IBM Domino Server stores this informations in root of tree.
Would it be possible to exclude the assert.ok for the search base and set this as optional?
function LdapAuth(opts) {
this.opts = opts;
assert.ok(opts.url, 'LDAP server URL not defined (opts.url)');
assert.ok(opts.searchBase, 'Search base not defined (opts.searchBase)');
assert.ok(opts.searchFilter, 'Search filter not defined (opts.searchFilter)');
Thank you for the response.
node-ldapjs 1.0.0 has been released.
ldapauth-fork still depends on ldapjs 0.7.1 explicitly.
are there plans to update this in the near future?
Hello,
I have an use case in which I need to authenticate the users belonging to a specific group only. If the user does not belong to the mentioned group, authentication should fail. I tried various approach for the filters, but none of them are working as expected. Below are the attempts that I tried:
searchFilter : "(&(sAMAccountName={{username}})(memberOf=testGroup))"
searchFilter : "(sAMAccountName={{username}})", groupSearchFilter : "(member=testGroup)"
For the first one, I always get no such user: "prerak"
even if the user is member of the testGroup
group.
For the second one, no matter what, the authentication is always successful, even if the group name is a random string.
So, how can I make the authentication work?
I am trying to wrap my ldap connection in a promise thereby catching all kinds of errors that could occur. Say my ldap server were to go down, and since the library only emits error events, how could I handle the emitted error such as a timeout? This is my code so far:
// Convert LDAP async call to return a Promise.
protected async authenticateLdap(ldapConnection: LdapAuth, username: string, password: string): Promise<ILdapUser> {
return new Promise<ILdapUser>((resolve, reject) => {
// Comes in deferred, crashing the thread (uncaughtException)
ldapConnection.on('error', function (msg: string) {
reject(err);
});
ldapConnection.authenticate(username, password, (err: any, result: ILdapUser) => {
if (err) {
reject(err)
} else {
resolve(result);
}
});
});
}
I considered using the connectTimeout ldapjs option but it would have to be applied on every auth attempt. How would you guys do it otherwise ? Would't we need a success event such as
ldapConnection.on('success', function () {
resolve();
});
Thanks for the help
The username is not filtered as per ldap specifications so the code seems to be vulnerable to ldap injection: https://www.owasp.org/index.php/LDAP_injection
I think {{username}}
should be available in the groupSearchFilter
.
This would require to edit this line. This would allow to filter groups by memberUid
.
I would gladly open a PR if this is acceptable.
This is causing an unhandled 'error' event when ever the connection to the LDAP server is down.
node-ldapauth-fork/lib/ldapauth.js
Lines 155 to 157 in f4f9f30
AFAICS, it seems that you are waiting for a callback that will never be called ?
See: https://github.com/joyent/node-ldapjs/blob/master/lib/client/client.js#L844-L847
If the ldap client periodically closes idle connections, an error
event will bubble up from ldapjs
to the top of the stack & kill the process. We see this with ECONNRESET errors that terminate the process.
Thing is, this module will check if it has a connection open and if not open it whenever calling into authenticate
.... the best way to deal with it seems to be to attach a dummy error handler to the client:
const ldapClient = LdapClient({...options})
ldapClient.on('error', () => { console.log('worry not!' }) // <-- clients need this or risk process termination
module.exports = (req, res, next) => {
ldapClient.authenticate(uname, password, (err, user) => {
if (err) { return next(err) } // <-- errors from reconnect after failed connection are handled here
req.user = user
next()
})
})
Or, if the library wants to handle it - it just needs to not re-emit the error event here:
https://github.com/vesse/node-ldapauth-fork/blob/v4.0.2/lib/ldapauth.js#L158
I'm not sure if there are things I'm missing here, so it might be best to leave this to the client to handle... hence my first comment on add this to the basicAuth example
in the readme.
Namely,
These are only passed to ldap.createClient from ldapjs, not used anywhere else. However, ldapjs does not use these options.
I get the following error when trying to use ldapauth on a (tls) secured ldap server. Not sure this is related to my config, to ldapauth-fork or to ldapjs.
~/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:111
closeSocket.on('close', function onClose(had_err) {
^
TypeError: Cannot read property 'on' of undefined
at setupSocket (~/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:111:14)
at Client._connect (~/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:742:3)
at new Client (~/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/client.js:247:22)
at Object.createClient (~/node_modules/ldapauth-fork/node_modules/ldapjs/lib/client/index.js:60:12)
at new LdapAuth (~/node_modules/ldapauth-fork/lib/ldapauth.js:129:28)
My config is as follows
var options = {
"url": "ldaps://ldap.MY_DOMAIN.com:636",
"bindDn": "cn=master-read,dc=MY_DOMAIN,dc=com",
"bindCredentials": "MyLdapPassword",
"searchBase": "dc=MY_DOMAIN,dc=com",
"searchFilter": "(&(objectClass=inetOrgPerson)(mailRoutingAddress={{username}}))",
"tlsOptions": {
"cert": "-----BEGIN CERTIFICATE-----\nNOT_SHOWN\n-----END CERTIFICATE-----"
}
};
I can get all this to work if I replace line 108 of ldapjs/lib/client/client.js by:
var closeSocket = (opts.secure ? socket.socket || socket : socket);
Version of node:
0.12.0
If I have worng username the message error was :"no such user: "admin",
But If I have correct username and worng password the message is :"InvalidCredentialsError: 8009030C: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db "
I'm running LDAP with StartTLS on port 389. When I'm trying to connect to LDAP I'm getting the following error message:
ConfidentialityRequiredError: TLS confidentiality required
Configuration:
server: {
url: 'ldap://localhost:389',
bindDN: 'cn=ldap,ou=services,dc=example,dc=com',
bindCredentials: 'password',
searchBase: 'ou=people,dc=example,dc=com',
searchFilter: '(cn={{username}})',
tlsOptions: {
ca: [fs.readFileSync('/etc/pki/ca/ca.crt')]
}
}
When changing configuration to:
server: {
url: 'ldaps://localhost:389',
bindDN: 'cn=ldap,ou=services,dc=example,dc=com',
bindCredentials: 'password',
searchBase: 'ou=people,dc=example,dc=com',
searchFilter: '(cn={{username}})',
tlsOptions: {
ca: [fs.readFileSync('/etc/pki/ca/ca.crt')]
}
}
I'm getting error message:
Error: socket hang up
From the ldapjs documentation I've been able to find out that you need to initiate StartTLS:
var ldap = require('ldapjs');
var client = ldap.createClient({
url: 'ldap://127.0.0.1:1389'
});
...
var opts = {
ca: [fs.readFileSync('mycacert.pem')]
};
client.starttls(opts, function(err, res) {
assert.ifError(err);
// Client communication now TLS protected
});
It seems to me that this modules create the connection using ldapjs:
var ldap = require('ldapjs');
...
this._adminClient = ldap.createClient(this.clientOpts);
this._userClient = ldap.createClient(this.clientOpts);
I've tried to add starttls in the code:
this._adminClient.starttls(opts.tlsOptions, function(err, res) {
assert.ifError(err);
// Client communication now TLS protected
});
...
this._uesrCleint.starttls(opts.tlsOptions, function(err, res) {
assert.ifError(err);
// Client communication now TLS protected
});
but that does not work
TypeError: Cannot convert undefined or null to object
at wrapper (/opt/example/node_modules/wrappy/wrappy.js:27:14)
at Client.starttls (/opt/example/node_modules/ldapjs/lib/client/client.js:880:14)
at new LdapAuth (/opt/example/node_modules/ldapauth-fork/lib/ldapauth.js:105:21)
at Strategy.handleAuthentication (/opt/example/node_modules/passport-ldapauth/lib/passport-ldapauth/strategy.js:272:10)
at Strategy.authenticate (/opt/example/node_modules/passport-ldapauth/lib/passport-ldapauth/strategy.js:337:33)
at attempt (/opt/example/node_modules/passport/lib/middleware/authenticate.js:361:16)
at authenticate (/opt/example/node_modules/passport/lib/middleware/authenticate.js:362:7)
at Layer.handle [as handle_request] (/opt/example/node_modules/express/lib/router/layer.js:95:5)
at next (/opt/example/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/opt/example/node_modules/express/lib/router/route.js:112:3)
What am I doing wrong? Did I forgot something?
Hi,
We have a node app using node-ldapauth-fork (through passport-ldapauth) for authentication. The LDAP certificate recently changed, and the new one doesn't have a "subject", although it has an "altName". This appears to be causing our app to reject the LDAP server.
The problem may be this reported node bug: nodejs/node#11771
So possibly it has nothing to do with node-ldapauth-fork. However, I wanted to ask whether you're seeing this error with similar certificates, and whether there's a workaround for this.
If I have correct username and empty password
Then authentication still successfully,
I think it was a bug
I am trying to connect ldap server using your library. The problem is i get the following error :
LDAP auth error:unexpected number of matches(10) for "CN=simple One,CN=Users,DC=test,DC=local" username
When i use library to connect to the ldap server using :
var config = {
ldap: {
url: "ldap://54.227.207.201:389",
bindDn: "CN=ritesh simplicity,CN=Users,DC=test,DC=local",
bindCredentials: "p4$$w0rd@!",
searchBase: "DC=test,DC=local",
searchFilter: "(objectClass=user)"
}
};
var ldap = new LdapAuth({
url: config.ldap.url,
bindDn: config.ldap.bindDn,
bindCredentials: config.ldap.bindCredentials,
searchBase: config.ldap.searchBase,
searchFilter: config.ldap.searchFilter,
//log4js: require('log4js'),
cache: true
});
app.post('/process_post', urlencodedParser, function (req, res) {
var username="CN="+req.body.first_name+",CN=Users,DC=test,DC=local";
var password=req.body.last_name;
ldap.authenticate(username, password, function (err, user) {
if (err) {
console.log("LDAP auth error: %s", err);
}
console.log("User Successful",user);
});
})
Please guide me through the issue i am facing.
> [email protected] install /Users/mcc1/Documents/workspace/allowanceclaims/node_modules/ldapauth-fork/node_modules/ldapjs/node_modules/dtrace-provider
> node-gyp rebuild
ACTION binding_gyp_libusdt_target_build_libusdt .
Building libusdt for x86_64
rm -f *.gch
rm -f *.o
rm -f libusdt.a
rm -f test_usdt
rm -f test_usdt32
rm -f test_usdt64
rm -f test_mem_usage
gcc -O2 -arch x86_64 -c -o usdt.o usdt.c
usdt.c:212:9: warning: implicit declaration of function 'usdt_dof_section_free' is invalid in C99
[-Wimplicit-function-declaration]
usdt_dof_section_free(&strtab);
^
usdt.c:238:9: warning: implicit declaration of function 'usdt_dof_file_free' is invalid in C99
[-Wimplicit-function-declaration]
usdt_dof_file_free(provider->file);
^
2 warnings generated.
gcc -O2 -arch x86_64 -c -o usdt_dof_file.o usdt_dof_file.c
gcc -arch x86_64 -o usdt_tracepoints.o -c usdt_tracepoints_x86_64.s
gcc -O2 -arch x86_64 -c -o usdt_probe.o usdt_probe.c
gcc -O2 -arch x86_64 -c -o usdt_dof.o usdt_dof.c
gcc -O2 -arch x86_64 -c -o usdt_dof_sections.o usdt_dof_sections.c
rm -f libusdt.a
ar cru libusdt.a usdt.o usdt_dof_file.o usdt_tracepoints.o usdt_probe.o usdt_dof.o usdt_dof_sections.o
ranlib libusdt.a
TOUCH Release/obj.target/libusdt.stamp
CXX(target) Release/obj.target/DTraceProviderBindings/dtrace_provider.o
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:69:44: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> New(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:70:45: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> Fire(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:87:44: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> New(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:88:49: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> AddProbe(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:89:52: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> RemoveProbe(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:90:47: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> Enable(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:91:48: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> Disable(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
In file included from ../dtrace_provider.cc:1:
../dtrace_provider.h:92:45: error: no type named 'Arguments' in namespace 'v8'; did you mean
'v8::internal::Arguments'?
static v8::Handle<v8::Value> Fire(const v8::Arguments& args);
^~~~~~~~~~~~~
v8::internal::Arguments
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:127:7: note: 'v8::internal::Arguments' declared here
class Arguments;
^
../dtrace_provider.cc:23:17: error: calling a protected constructor of class 'v8::HandleScope'
HandleScope scope;
^
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:816:13: note: declared protected here
V8_INLINE HandleScope() {}
^
../dtrace_provider.cc:25:55: error: cannot initialize a parameter of type 'v8::Isolate *' with an lvalue of type
'v8::Handle<v8::Value> (const v8::internal::Arguments &)'
Local<FunctionTemplate> t = FunctionTemplate::New(DTraceProvider::New);
^~~~~~~~~~~~~~~~~~~
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:3456:16: note: passing argument to parameter 'isolate' here
Isolate* isolate,
^
../dtrace_provider.cc:26:58: error: 'New' is a private member of 'v8::PersistentBase<v8::FunctionTemplate>'
constructor_template = Persistent<FunctionTemplate>::New(t);
^
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:572:23: note: declared private here
V8_INLINE static T* New(Isolate* isolate, T* that);
^
../dtrace_provider.cc:26:28: error: too few arguments to function call, expected 2, have 1; did you mean
'DTraceProbe::New'?
constructor_template = Persistent<FunctionTemplate>::New(t);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DTraceProbe::New
../dtrace_provider.h:69:34: note: 'DTraceProbe::New' declared here
static v8::Handle<v8::Value> New(const v8::Arguments& args);
^
../dtrace_provider.cc:27:25: error: member reference type 'Persistent<v8::FunctionTemplate>' is not a pointer; maybe
you meant to use '.'?
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
~~~~~~~~~~~~~~~~~~~~^~
.
../dtrace_provider.cc:27:27: error: no member named 'InstanceTemplate' in 'v8::Persistent<v8::FunctionTemplate,
v8::NonCopyablePersistentTraits<v8::FunctionTemplate> >'
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
~~~~~~~~~~~~~~~~~~~~ ^
../dtrace_provider.cc:28:25: error: member reference type 'Persistent<v8::FunctionTemplate>' is not a pointer; maybe
you meant to use '.'?
constructor_template->SetClassName(String::NewSymbol("DTraceProvider"));
~~~~~~~~~~~~~~~~~~~~^~
.
../dtrace_provider.cc:28:27: error: no member named 'SetClassName' in 'v8::Persistent<v8::FunctionTemplate,
v8::NonCopyablePersistentTraits<v8::FunctionTemplate> >'
constructor_template->SetClassName(String::NewSymbol("DTraceProvider"));
~~~~~~~~~~~~~~~~~~~~ ^
../dtrace_provider.cc:28:48: error: no member named 'NewSymbol' in 'v8::String'
constructor_template->SetClassName(String::NewSymbol("DTraceProvider"));
~~~~~~~~^
../dtrace_provider.cc:30:31: error: no viable conversion from 'Persistent<v8::FunctionTemplate>' to
'v8::Handle<v8::FunctionTemplate>'
NODE_SET_PROTOTYPE_METHOD(constructor_template, "addProbe", DTraceProvider::AddProbe);
^~~~~~~~~~~~~~~~~~~~
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:196:26: note: candidate constructor
(the implicit copy constructor) not viable: no known conversion from 'Persistent<v8::FunctionTemplate>' to
'const v8::Handle<v8::FunctionTemplate> &' for 1st argument
template <class T> class Handle {
^
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:213:32: note: candidate template ignored: could not match 'Handle'
against 'Persistent'
template <class S> V8_INLINE Handle(Handle<S> that)
^
/Users/mcc1/.node-gyp/0.12.2/src/node.h:244:72: note: passing argument to parameter 'recv' here
inline void NODE_SET_PROTOTYPE_METHOD(v8::Handle<v8::FunctionTemplate> recv,
^
../dtrace_provider.cc:31:31: error: no viable conversion from 'Persistent<v8::FunctionTemplate>' to
'v8::Handle<v8::FunctionTemplate>'
NODE_SET_PROTOTYPE_METHOD(constructor_template, "removeProbe", DTraceProvider::RemoveProbe);
^~~~~~~~~~~~~~~~~~~~
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:196:26: note: candidate constructor
(the implicit copy constructor) not viable: no known conversion from 'Persistent<v8::FunctionTemplate>' to
'const v8::Handle<v8::FunctionTemplate> &' for 1st argument
template <class T> class Handle {
^
/Users/mcc1/.node-gyp/0.12.2/deps/v8/include/v8.h:213:32: note: candidate template ignored: could not match 'Handle'
against 'Persistent'
template <class S> V8_INLINE Handle(Handle<S> that)
^
/Users/mcc1/.node-gyp/0.12.2/src/node.h:244:72: note: passing argument to parameter 'recv' here
inline void NODE_SET_PROTOTYPE_METHOD(v8::Handle<v8::FunctionTemplate> recv,
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [Release/obj.target/DTraceProviderBindings/dtrace_provider.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:269:23)
gyp ERR! stack at ChildProcess.emit (events.js:110:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:1074:12)
gyp ERR! System Darwin 14.1.0
gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/mcc1/Documents/workspace/allowanceclaims/node_modules/ldapauth-fork/node_modules/ldapjs/node_modules/dtrace-provider
gyp ERR! node -v v0.12.2
gyp ERR! node-gyp -v v1.0.3
gyp ERR! not ok
npm WARN optional dep failed, continuing [email protected]
[email protected] node_modules/ldapauth-fork
├── [email protected]
├── [email protected]
└── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected])
MCCs-MacBook-Pro:allowanceclaims mcc1$ dtrace-provider -v
-bash: dtrace-provider: command not found
Is there anyway to implement ldap authentication in angular2 by using server side script? I am trying to migrate my web application to Angular2 and I am done with most of the UI part now I left with Authentication. I have used LDAP as a web reference in my .net project. ldap authentication in the past app where I connect to my ldaps://example.host:636/ with userDN and password. I am looking for the way to do authentication using ldap. I looked into this link (https://auth0.com/authenticate/angular2/ldap) but didn't get where to register or give my ldap server details to work with, think that is available for paid users. Please suggest me the best way to implement authentication for Angular2 without any other extra cost by using server side scripting....
I am testing ldapauth-fork against ldap url being unreachable and i have noticed that on "auth.on('error', function (err)" is executed twice on error.
var auth= new LdapAuth({ url: some_unreachable_url ... }
auth.on('error', function (err) { console.log("hello"); }
In the example above with "hello" is printed twice.
Using Node v0.10.29 and the latest version of log4js (0.6.15), errors from ldap are logged as [object Object].
Ex:
ldap authenticate: bind error: [object Object]
I currently have a patched version that outputs JSON.stringify(err)
, which worked for my purposes, but I don't think that's the best way to do it. Perhaps err.message
or a combination of err.code
and err.name
?
Hey dear folks,
ive got the following issue. When i try to connect it throws this error
[21:21:05] [ERROR] - { ConnectionError: 1__ldap://192.168.3.2:636 closed
at /home/appuser/apitest/node_modules/ldapjs/lib/client/client.js:1277:17
at Array.forEach (native)
at Client._onClose (/home/appuser/apitest/node_modules/ldapjs/lib/client/client.js:1272:19)
at Socket.g (events.js:292:16)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at TCP._handle.close [as _onclose] (net.js:497:12)
lde_message: '1__ldap://192.168.3.2:636 closed',
lde_dn: null }
The config follows linuxmuster.net , but here the ldapoptions
const ldapoptions = {
url: config.ldap,
searchBase: 'ou=accounts,dc=linuxmuster,dc=local',
searchFilter: '(uid={{username}})',
reconnect: true
}
Somebody know the problem/error? And can help me out with this ^^
We are using:
[email protected]
within docker[email protected]
that include [email protected]
[email protected]
within dockerWe have GItLab-CI runner that run npm install --registry https://our.registry.com
for the project.
I can connect repetitively multiple time to the LDAP, until:
In node 10.1.0
http <-- 200, user: me(172.18.0.1 via 172.16.14.10), req: 'GET /node-int64', bytes: 0/2481
http --> 304, req: 'GET https://registry.npmjs.org/multicast-dns-service-types' (streaming)
http --> 304, req: 'GET https://registry.npmjs.org/multicast-dns-service-types', bytes: 0/0
debug--- connected after 1 attempt(s)
debug--- connected after 1 attempt(s)
debug--- connected after 1 attempt(s)
debug--- failed to connect after 1 attempts
fatal--- uncaught exception, please report this
Error: Client network socket disconnected before secure TLS connection was established
at TLSSocket.onConnectEnd (_tls_wrap.js:1092:19)
at Object.onceWrapper (events.js:273:13)
at TLSSocket.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1086:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
In node 8.11.2
info --> making request: 'GET https://registry.npmjs.org/array-unique'
debug--- connected after 1 attempt(s)
debug--- connected after 1 attempt(s)
fatal--- uncaught exception, please report this
TypeError: (groups || []).concat is not a function
at authenticatedUser (/usr/local/lib/node_modules/verdaccio/build/lib/auth.js:372:32)
at /usr/local/lib/node_modules/verdaccio/build/lib/auth.js:105:26
at sendResult (/usr/local/lib/node_modules/verdaccio-ldap/node_modules/ldapjs/lib/client/client.js:1395:12)
at messageCallback (/usr/local/lib/node_modules/verdaccio-ldap/node_modules/ldapjs/lib/client/client.js:1421:16)
at /usr/local/lib/node_modules/verdaccio-ldap/node_modules/ldapjs/lib/client/client.js:1282:14
at Array.forEach (<anonymous>)
at Client._onClose (/usr/local/lib/node_modules/verdaccio-ldap/node_modules/ldapjs/lib/client/client.js:1272:19)
at Object.onceWrapper (events.js:272:13)
at TLSSocket.emit (events.js:180:13)
at _handle.close (net.js:541:12)
at TCP.done [as _onclose] (_tls_wrap.js:379:7)
We can connect repetitively to the LDAP but then this error happens and prevent us totally from using our verdaccio registry.
Is there a way to prevent such bug ? The verdaccio-ldap plugin is not supporting starttls, using starttls ,
Thanks for the library! Using this in a new project and was surprised to see authenticate taking as much time as it did when I had cache enabled. I had 17
parallel jobs executing which added about 1.5
- 2.0
seconds vs my own auth cache stored in redis. Digging through the code left me at 1 spot, bcrypt.compareSync()
(I didn't trace all this so it could be something else).
Would it be possible to use a different hash?
Would it be possible to use the native c++
module and backfill with the pure js?
Would it be possible to simply hash the username/password jointly as the cache key (using something faster than bcrypt
) and the mere existence of the cache entry means it's legit?
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.