Hi i am trying to setup LDAP authentication for my meteorJS app and i am following the steps listed in here https://janikvonrotz.ch/2017/02/08/meteor-register-ldap-login-request-handler/
i changed the search filter from mail to username and pushed everything inside of Meteor.startup()
here is my code set up
UI code written in /imports/ui/loginform.jsx
let loginUserWithLDAP = (username, password, callback) => {
var loginRequest = {
ldap: true,
username: username,
email: username+"@company.com",
pass: password,
}
Accounts.callLoginMethod({
methodArguments: [loginRequest],
userCallback: callback
})
}
in my /server/ldap.js
Meteor.startup(() => {
var ldapAuth = {
url: 'ldap://company.com:389',
searchOu: 'ou=Employees,ou=\'company Users\', dc=company,dc=com',
searchQuery: (username) => {
return {
filter: '(&(objectclass=user)(samaccountname='+username+'))',
scope: 'sub'
}
}
}
ldapAuth.checkAccount = (options) => {
options = options || {}
ldapAuth.client = ldap.createClient({
url: ldapAuth.url
})
let dn = ['company', 'com']
var future = new Future()
ldapAuth.client.search(
ldapAuth.searchOu,
ldapAuth.searchQuery(options.username),
(error, result)=> {
assert.ifError(error)
result.on('searchEntry', (entry) => {
dn.push(entry.objectName)
return ldapAuth.profile = {
firstname: entry.object.cn,
lastname: entry.object.sn
}
})
result.on('error', function(error){
throw new Meteor.Error(500, "LDAP server error")
})
result.on('end', function(){
if (dn.length === 0) {
future['return'](false)
return false
}
return ldapAuth.client.bind(dn[0], options.pass, (error) =>{
if (error){
future['return'](false)
return false
}
return ldapAuth.client.unbind((error) => {
assert.ifError(error)
return future['return'](!error)
});
})
})
})
return future.wait()
}
Accounts.registerLoginHandler('ldap', (loginRequest)=>{
if (!loginRequest.ldap) {
return undefined
}
if (ldapAuth.checkAccount(loginRequest)){
var userId = null
var user = Meteor.users.findOne({"username": loginRequest.username })
if (!user) {
userId = Accounts.createUser({
username: loginRequest.username,
password: loginRequest.pass,
profile: ldapAuth.profile,
roles: ['user'],
})
Meteor.users.update(userId, { $set: { 'emails.0.verified': true } })
} else {
userId = user._id
}
let stampedToken = Accounts._generateStampedLoginToken()
let hashStampedToken = Accounts._hashStampedToken(stampedToken)
Meteor.users.update(userId,
{ $push: {'services.resume.loginTokens': hashStampedToken } }
)
return {
userId: userId,
token: stampedToken.token
}
}
})
});
In my debugging i found that its erroring out at
result.on('error', function(error){
throw new Meteor.Error(500, "LDAP server error")
})
due to '000004DC: LdapErr: DSID-0C0907E9, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v2580'
what does this mean?
What is my code missing?
In short you need to define a search user that does the binding with the LDAP directory.
The post is outdated, I've got you this example: https://github.com/janikvonrotz/Zenkom/blob/0583f01abca96847178a248ff446d84c754965e9/server/actions/ldap.js#L18
Setup the search user like this:
"searchUser": {
"dn": "CN=username,OU=org,DC=company,DC=ch",
"password": "password"
}
The bind user is simply for search the directory. Another bind is executed to authenticate the found user.