ldap-authentication
Advanced tools
Comparing version 2.2.1 to 2.2.4
122
index.js
@@ -88,2 +88,47 @@ const assert = require('assert') | ||
// search a groups which user is member | ||
async function _searchUserGroups( | ||
ldapClient, | ||
searchBase, | ||
user, | ||
groupClass | ||
) { | ||
return new Promise(function (resolve, reject) { | ||
ldapClient.search( | ||
searchBase, | ||
{ | ||
filter: `(&(objectclass=${groupClass})(member=${user.dn}))`, | ||
scope: 'sub', | ||
}, | ||
function (err, res) { | ||
var groups = [] | ||
if (err) { | ||
reject(err) | ||
ldapClient.unbind() | ||
return | ||
} | ||
res.on('searchEntry', function (entry) { | ||
groups.push(entry.object) | ||
}) | ||
res.on('searchReference', function (referral) { | ||
console.log('referral: ' + referral.uris.join()) | ||
}) | ||
res.on('error', function (err) { | ||
console.error('error: ' + err.message) | ||
reject(err) | ||
ldapClient.unbind() | ||
}) | ||
res.on('end', function (result) { | ||
if (result.status != 0) { | ||
reject(new Error('ldap search status is not 0, search failed')) | ||
} else { | ||
resolve(groups) | ||
} | ||
ldapClient.unbind() | ||
}) | ||
} | ||
) | ||
}) | ||
} | ||
async function authenticateWithAdmin( | ||
@@ -97,10 +142,17 @@ adminDn, | ||
starttls, | ||
ldapOpts | ||
ldapOpts, | ||
groupsSearchBase, | ||
groupClass | ||
) { | ||
var ldapAdminClient = await _ldapBind( | ||
adminDn, | ||
adminPassword, | ||
starttls, | ||
ldapOpts | ||
) | ||
var ldapAdminClient | ||
try { | ||
ldapAdminClient = await _ldapBind( | ||
adminDn, | ||
adminPassword, | ||
starttls, | ||
ldapOpts | ||
) | ||
} catch (error) { | ||
throw {admin:error} | ||
} | ||
var user = await _searchUser( | ||
@@ -123,4 +175,24 @@ ldapAdminClient, | ||
var userDn = user.dn | ||
let ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
let ldapUserClient | ||
try { | ||
ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
} catch (error) { | ||
throw error | ||
} | ||
ldapUserClient.unbind() | ||
if (groupsSearchBase && groupClass) { | ||
try { | ||
ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
} catch (error) { | ||
throw error | ||
} | ||
var groups = await _searchUserGroups( | ||
ldapUserClient, | ||
groupsSearchBase, | ||
user, | ||
groupClass | ||
); | ||
user.groups = groups; | ||
ldapUserClient.unbind() | ||
} | ||
return user | ||
@@ -136,5 +208,12 @@ } | ||
starttls, | ||
ldapOpts | ||
ldapOpts, | ||
groupsSearchBase, | ||
groupClass | ||
) { | ||
let ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
let ldapUserClient | ||
try { | ||
ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
} catch (error) { | ||
throw error | ||
} | ||
if (!usernameAttribute || !userSearchBase) { | ||
@@ -161,2 +240,17 @@ // if usernameAttribute is not provided, no user detail is needed. | ||
ldapUserClient.unbind() | ||
if (groupsSearchBase && groupClass) { | ||
try { | ||
ldapUserClient = await _ldapBind(userDn, userPassword, starttls, ldapOpts) | ||
} catch (error) { | ||
throw error | ||
} | ||
var groups = await _searchUserGroups( | ||
ldapUserClient, | ||
groupsSearchBase, | ||
user, | ||
groupClass | ||
); | ||
user.groups = groups; | ||
ldapUserClient.unbind() | ||
} | ||
return user | ||
@@ -196,3 +290,5 @@ } | ||
options.starttls, | ||
options.ldapOpts | ||
options.ldapOpts, | ||
options.groupsSearchBase, | ||
options.groupClass | ||
) | ||
@@ -208,3 +304,5 @@ } | ||
options.starttls, | ||
options.ldapOpts | ||
options.ldapOpts, | ||
options.groupsSearchBase, | ||
options.groupClass | ||
) | ||
@@ -211,0 +309,0 @@ } |
{ | ||
"name": "ldap-authentication", | ||
"version": "2.2.1", | ||
"version": "2.2.4", | ||
"description": "A simple async nodejs library for LDAP user authentication", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "jest" | ||
"test": "node test/jasmine.js" | ||
}, | ||
@@ -15,3 +15,17 @@ "repository": { | ||
"ldap", | ||
"authentication" | ||
"authenticate", | ||
"authentication", | ||
"ldapjs", | ||
"security", | ||
"simple", | ||
"lightweight", | ||
"fast", | ||
"async", | ||
"passport", | ||
"passportjs", | ||
"login", | ||
"password", | ||
"username", | ||
"ldap-authentication", | ||
"ldap-authenticate" | ||
], | ||
@@ -25,7 +39,8 @@ "author": "Jingshao Chen", | ||
"dependencies": { | ||
"ldapjs": "^2.0.0" | ||
"ldapjs": "^2.1.1" | ||
}, | ||
"devDependencies": { | ||
"jest": "^26.0.1" | ||
"jasmine": "^3.6.1", | ||
"jasmine-console-reporter": "^3.1.0" | ||
} | ||
} |
@@ -70,2 +70,17 @@ # A Simple node Library that Authenticates a User Against an LDAP/AD Server | ||
#### User authenticate and return user details with groups | ||
```javascript | ||
let authenticated = await authenticate({ | ||
ldapOpts: { url: 'ldap://ldap.forumsys.com' }, | ||
userDn: 'uid=gauss,dc=example,dc=com', | ||
userPassword: 'password', | ||
userSearchBase: 'dc=example,dc=com', | ||
usernameAttribute: 'uid', | ||
username: 'gauss', | ||
groupsSearchBase: 'dc=example,dc=com', | ||
groupClass: 'group' | ||
}) | ||
``` | ||
#### Complete example | ||
@@ -139,1 +154,3 @@ | ||
- `starttls`: Boolean. Use `STARTTLS` or not | ||
- `groupsSearchBase`: if specified with groupClass, will serve as search base for authenticated user groups | ||
- `groupClass`: if specified with groupsSearchBase, will be used as objectClass in search filter for authenticated user groups |
const { authenticate, LdapAuthenticationError } = require('../index.js') | ||
describe('ldap-authentication test', () => { | ||
test('Use an admin user to authenticate a regular user', async () => { | ||
it('Use an admin user to authenticate a regular user', async () => { | ||
let options = { | ||
@@ -20,3 +20,3 @@ ldapOpts: { | ||
}) | ||
test('Use an regular user to authenticate iteself', async () => { | ||
it('Use an regular user to authenticate iteself', async () => { | ||
let options = { | ||
@@ -36,3 +36,3 @@ ldapOpts: { | ||
}) | ||
test('Use an regular user to authenticate iteself without search', async () => { | ||
it('Use an regular user to authenticate iteself without search', async () => { | ||
let options = { | ||
@@ -51,3 +51,3 @@ ldapOpts: { | ||
describe('ldap-authentication negative test', () => { | ||
test('wrong admin user should fail', async () => { | ||
it('wrong admin user should fail', async () => { | ||
let options = { | ||
@@ -72,3 +72,3 @@ ldapOpts: { | ||
}) | ||
test('wrong admin password should fail', async () => { | ||
it('wrong admin password should fail', async () => { | ||
let options = { | ||
@@ -93,3 +93,3 @@ ldapOpts: { | ||
}) | ||
test('admin auth wrong username should fail', async () => { | ||
it('admin auth wrong username should fail', async () => { | ||
let options = { | ||
@@ -114,3 +114,3 @@ ldapOpts: { | ||
}) | ||
test('admin auth wrong user password should fail', async () => { | ||
it('admin auth wrong user password should fail', async () => { | ||
let options = { | ||
@@ -135,3 +135,3 @@ ldapOpts: { | ||
}) | ||
test('user auth wrong username should fail', async () => { | ||
it('user auth wrong username should fail', async () => { | ||
let options = { | ||
@@ -155,3 +155,3 @@ ldapOpts: { | ||
}) | ||
test('user auth wrong user password should fail', async () => { | ||
it('user auth wrong user password should fail', async () => { | ||
let options = { | ||
@@ -175,3 +175,3 @@ ldapOpts: { | ||
}) | ||
test('Use an regular user to authenticate iteself without search with wrong password should fail', async () => { | ||
it('Use an regular user to authenticate iteself without search with wrong password should fail', async () => { | ||
let options = { | ||
@@ -191,3 +191,3 @@ ldapOpts: { | ||
}) | ||
test('Wrong options give LdapAuthenticationError', async () => { | ||
it('Wrong options give LdapAuthenticationError', async () => { | ||
let options = { | ||
@@ -211,3 +211,3 @@ ldapOpts: { | ||
}) | ||
test('Unreachable ldap server should throw error', async () => { | ||
it('Unreachable ldap server should throw error', async () => { | ||
let options = { | ||
@@ -214,0 +214,0 @@ ldapOpts: { |
22011
8
574
155
2
Updatedldapjs@^2.1.1