Fix ldapjs 3.x API: use entry.pojo for search results
- ldapjs 3.x returns entries as entry.pojo not entry.object - Access attributes via entry.pojo.attributes array - Clean up debug logging - Restore group membership filter for production
This commit is contained in:
@@ -79,15 +79,19 @@ app.use((req, res, next) => {
|
||||
|
||||
async function authenticateLDAP(username, password) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = ldap.createClient({ url: CONFIG.ldap.url });
|
||||
const client = ldap.createClient({
|
||||
url: CONFIG.ldap.url,
|
||||
timeLimit: 10,
|
||||
sizeLimit: 100
|
||||
});
|
||||
|
||||
client.on('error', (err) => {
|
||||
console.error('[LDAP] Connection error:', err.message);
|
||||
reject(new Error('LDAP connection failed'));
|
||||
});
|
||||
|
||||
// Step 1: Bind with service account (if configured) to search for user
|
||||
const doSearch = () => {
|
||||
// Build search filter from config, replacing {{username}} with actual username
|
||||
const filter = CONFIG.ldap.searchFilter.replace('{{username}}', username);
|
||||
|
||||
const searchOptions = {
|
||||
@@ -98,6 +102,31 @@ async function authenticateLDAP(username, password) {
|
||||
|
||||
let userDN = null;
|
||||
const user = { username };
|
||||
let searchComplete = false;
|
||||
|
||||
const finishSearch = () => {
|
||||
if (searchComplete) return;
|
||||
searchComplete = true;
|
||||
|
||||
if (!userDN) {
|
||||
client.destroy();
|
||||
reject(new Error('User not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2: Bind as the user to verify password
|
||||
client.bind(userDN, password, (err) => {
|
||||
if (err) {
|
||||
client.destroy();
|
||||
reject(new Error('Invalid credentials'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[LDAP] Authenticated:', username);
|
||||
client.destroy();
|
||||
resolve(user);
|
||||
});
|
||||
};
|
||||
|
||||
client.search(CONFIG.ldap.baseDN, searchOptions, (err, res) => {
|
||||
if (err) {
|
||||
@@ -107,48 +136,32 @@ async function authenticateLDAP(username, password) {
|
||||
}
|
||||
|
||||
res.on('searchEntry', (entry) => {
|
||||
userDN = entry.object.dn;
|
||||
user.dn = entry.object.dn;
|
||||
user.uid = entry.object.uid;
|
||||
user.cn = entry.object.cn;
|
||||
user.email = entry.object.mail;
|
||||
user.displayName = entry.object.displayName || entry.object.cn;
|
||||
user.groups = entry.object.memberOf
|
||||
? (Array.isArray(entry.object.memberOf) ? entry.object.memberOf : [entry.object.memberOf])
|
||||
: [];
|
||||
const pojo = entry.pojo;
|
||||
userDN = pojo.objectName;
|
||||
user.dn = pojo.objectName;
|
||||
for (const attr of pojo.attributes) {
|
||||
if (attr.type === 'uid') user.uid = attr.values[0];
|
||||
if (attr.type === 'cn') user.cn = attr.values[0];
|
||||
if (attr.type === 'mail') user.email = attr.values[0];
|
||||
if (attr.type === 'displayName') user.displayName = attr.values[0];
|
||||
if (attr.type === 'memberOf') user.groups = attr.values;
|
||||
}
|
||||
});
|
||||
|
||||
res.on('error', (err) => {
|
||||
console.error('[LDAP] Search error:', err.message);
|
||||
client.destroy();
|
||||
reject(err);
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
if (!userDN) {
|
||||
client.destroy();
|
||||
reject(new Error('User not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2: Bind as the user to verify password
|
||||
client.bind(userDN, password, (err) => {
|
||||
if (err) {
|
||||
client.destroy();
|
||||
reject(new Error('Invalid credentials'));
|
||||
return;
|
||||
}
|
||||
|
||||
client.destroy();
|
||||
resolve(user);
|
||||
});
|
||||
});
|
||||
res.on('end', () => finishSearch());
|
||||
});
|
||||
};
|
||||
|
||||
// If we have a service account bind, use it first
|
||||
if (CONFIG.ldap.bindDN && CONFIG.ldap.bindPassword) {
|
||||
client.bind(CONFIG.ldap.bindDN, CONFIG.ldap.bindPassword, (err) => {
|
||||
if (err) {
|
||||
console.error('[LDAP] Service bind failed:', err.message);
|
||||
client.destroy();
|
||||
reject(new Error('LDAP service bind failed'));
|
||||
return;
|
||||
@@ -156,7 +169,6 @@ async function authenticateLDAP(username, password) {
|
||||
doSearch();
|
||||
});
|
||||
} else {
|
||||
// No service bind - search anonymously (may not work with all LDAP servers)
|
||||
doSearch();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user