Last active
August 20, 2022 03:03
-
-
Save DavesCodeMusings/d1014d89f48122d67a3f9d3456f88a1d to your computer and use it in GitHub Desktop.
Example of LDAP user authentication using ldapjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| /** | |
| * Example of LDAP user authentication using ldapjs. | |
| * | |
| * Run like this: | |
| * auth.js ; echo $? | |
| * | |
| * A successful authentication will show output like this along with a return code of 0: | |
| * Connecting to: [ 'ldap://127.0.0.1:389' ] | |
| * TLS started. | |
| * Binding as: uid=search,dc=home | |
| * Searching ou=People,dc=home for: uid=dave | |
| * Rebinding as: uid=dave,ou=People,dc=home | |
| * Authenticated. | |
| * Disconnecting. | |
| * | |
| * Unsuccessful authentication will show error messages and a return code of 255. | |
| */ | |
| import {readFileSync} from 'fs'; | |
| import ldapjs from 'ldapjs'; | |
| // The following were tested using OpenLDAP and the PosixAccount object class. | |
| // Adjust as needed for your setup. | |
| const ldapURL = [ 'ldap://127.0.0.1:389' ]; // Array can contain additional LDAP servers to try. | |
| const bindDN = 'uid=search,dc=home'; | |
| const bindPassword = 'password'; | |
| const baseDN = 'ou=People,dc=home'; | |
| const usernameAttribute = 'uid'; | |
| const filter = '(objectClass=posixAccount)'; | |
| // In a real application, the user credentials would come from a login form. | |
| var username = 'dave'; | |
| var password = 'password'; | |
| process.exitCode = -1; // Return this value to the shell if not successful. | |
| // Most of the rest is pieced together from the documentation at: http://ldapjs.org/client.html | |
| // And a helpful example from 'kohleman' at: https://github.com/ldapjs/node-ldapjs/issues/326 | |
| console.debug('Connecting to server:', ldapURL); | |
| const client = ldapjs.createClient({ | |
| url: ldapURL | |
| }); | |
| client.on('error', (err) => { | |
| console.error('LDAP error:', err.message); | |
| }); | |
| client.on('connect', () => { | |
| const opts = { | |
| ca: [fs.readFileSync('/etc/ssl/certs/ca-certificates.crt', 'utf-8')], | |
| rejectUnauthorized: false // Helps with self-signed certs. | |
| }; | |
| client.starttls(opts, client.controls, (err) => { | |
| if (err) { | |
| console.error(err.message); | |
| client.unbind(() => { | |
| console.log('Disconnecting.'); | |
| }); | |
| } | |
| else { | |
| console.debug('TLS started.'); | |
| console.debug('Binding as:', bindDN); | |
| client.bind(bindDN, bindPassword, (err) => { | |
| if (err) { | |
| console.error(err.message); | |
| client.unbind(() => { | |
| console.log('Disconnecting.'); | |
| }); | |
| } | |
| else { | |
| const opts = { | |
| attributes: usernameAttribute, | |
| filter: `&${filter}(${usernameAttribute}=${username})`, | |
| scope: 'sub' | |
| }; | |
| console.debug('Searching', baseDN, 'for:', `${usernameAttribute}=${username}`); | |
| client.search(`${baseDN}`, opts, (err, res) => { | |
| let numMatch = 0; | |
| let userDN = ''; | |
| if (err) { | |
| console.error(err.message); | |
| client.unbind(() => { | |
| console.log('Disconnecting.'); | |
| }); | |
| } | |
| res.on('error', (err) => { | |
| console.error('Error:', err.message); | |
| client.unbind(() => { | |
| console.log('Disconnecting.'); | |
| }); | |
| }); | |
| res.on('searchEntry', (entry) => { // There was a match. | |
| numMatch++; | |
| userDN = entry.object.dn; | |
| }); | |
| res.on('end', () => { | |
| if (numMatch == 1) { | |
| console.debug('Rebinding as:', userDN); | |
| client.bind(userDN, password, (err) => { | |
| if (err) { | |
| console.error('Error:', err.message); | |
| } | |
| else { | |
| process.exitCode = 0; | |
| console.log('Authenticated.'); | |
| } | |
| }); | |
| } | |
| else if (numMatch > 1) { | |
| console.error('Multiple matches returned.'); | |
| } | |
| else { | |
| console.error('Not found.'); | |
| } | |
| client.unbind(() => { | |
| console.log('Disconnecting.'); | |
| }); | |
| }); | |
| }); | |
| } | |
| }); | |
| } | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment