Hey there,
this might be an odd request. I’m looking for someone who has experience with custom Meteor login handler and might be able to help me solve a basic problem. I’ve spent way to much time on building a simple ldap authentication handler myself. It shouldn’t be a big deal.
To explain the problem I need to give you some context. First the client code:
client/main.js
...
Meteor.loginUserWithLDAP = function (email, password, callback) {
let loginRequest = {
email: email,
pass: password,
ldap: true
}
Accounts.callLoginMethod({
methodArguments: [loginRequest],
userCallback: callback
})
}
...
When executing this method, an error is thrown immediately: unrecognized options for login request 400
And the user is not authenticated.
The error is thrown by the Accounts package (line 479): https://github.com/meteor/accounts/blob/master/packages/accounts-base/accounts_server.js
And the same time the server code is executed successfully.
server/ldap.js
import ldap from 'ldapjs'
import assert from 'assert'
import { Accounts } from 'meteor/accounts-base'
var client = ldap.createClient({
url: 'ldap://ldap.forumsys.com'
})
var bound = Meteor.bindEnvironment((callback) => {
return callback()
})
Accounts.registerLoginHandler('ldap', (loginRequest) => {
console.log('Login request received.', loginRequest)
if (!loginRequest.ldap) {
return undefined // don't handle
}
let bindUser = (dn, email, password, profile) => {
client.bind(dn, password, (error) => {
if(error) throw error
bound(() => {
var userId = null
var user = Meteor.users.findOne({ "emails.address" : email })
if (!user) {
userId = Accounts.createUser({
email: email,
password: password,
profile: 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 } }
)
console.log('Loggin')
return {
id: userId,
token: stampedToken.token
}
})
})
}
let options = {
filter: `(mail=${loginRequest.email})`,
scope: 'sub'
}
client.search('dc=example,dc=com', options, (error, result) => {
if(error) throw error
result.on('searchEntry', (entry) => {
let profile = {
firstname: entry.object.cn,
lastname: entry.object.sn
}
bindUser(entry.object.dn, entry.object.mail, loginRequest.pass, profile)
})
})
})
The server console tells me that the return statement has been reached.
I did quite a lot of research trying to solve this problem, but no success so far.
I’m not sure wether I’ve used the bind environment functions the right way, so this might be a source for mistakes.
Would be great if somebody could give me a strategy on how to solve this problem.