ldap-authentication 3.2.2 → 3.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/integration-test.yml +2 -2
- package/.github/workflows/npm-publish.yml +33 -0
- package/README.md +2 -2
- package/index.js +41 -1
- package/package.json +2 -2
- package/test/string.spec.js +20 -1
- package/test/test.spec.js +21 -1
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
run: sudo apt-get install -y ldap-utils
|
|
28
28
|
|
|
29
29
|
- name: Start containers
|
|
30
|
-
run: docker
|
|
30
|
+
run: docker compose -f "docker-compose.yml" up -d
|
|
31
31
|
|
|
32
32
|
- name: Wait for LDAP server to become available
|
|
33
33
|
uses: nick-fields/retry@v2
|
|
@@ -51,4 +51,4 @@ jobs:
|
|
|
51
51
|
|
|
52
52
|
- name: Stop containers
|
|
53
53
|
if: always()
|
|
54
|
-
run: docker
|
|
54
|
+
run: docker compose -f "docker-compose.yml" down
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
+
|
|
4
|
+
name: Publish to NPM
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [created]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: 20
|
|
18
|
+
- run: npm ci
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
publish-npm:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: 20
|
|
29
|
+
registry-url: https://registry.npmjs.org/
|
|
30
|
+
- run: npm ci
|
|
31
|
+
- run: npm publish
|
|
32
|
+
env:
|
|
33
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/README.md
CHANGED
|
@@ -187,7 +187,7 @@ In version 2, The user object has a `raw` field that has the raw data from the L
|
|
|
187
187
|
Buffer data can now be accessed by `user.raw.profilePhoto`, etc, instead of `user.profilePhoto`.
|
|
188
188
|
|
|
189
189
|
In version 3, the `raw` field is no longer used. Instead, append `;binary` to the attributes you
|
|
190
|
-
want to get back as
|
|
190
|
+
want to get back as base64-encoded string. Check the following example on how to get a user's profile photo:
|
|
191
191
|
|
|
192
192
|
```javascript
|
|
193
193
|
export async function verifyLogin(email: string, password: string) {
|
|
@@ -210,7 +210,7 @@ export async function verifyLogin(email: string, password: string) {
|
|
|
210
210
|
const profilePhoto = ldapUser['thumbnailPhoto;binary'];
|
|
211
211
|
|
|
212
212
|
/* using the image
|
|
213
|
-
<img src={`data:image/*;base64,${
|
|
213
|
+
<img src={`data:image/*;base64,${profilePhoto}`} />
|
|
214
214
|
*/
|
|
215
215
|
return { user: ldapUser };
|
|
216
216
|
}
|
package/index.js
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
const assert = require('assert')
|
|
2
2
|
const ldap = require('ldapjs')
|
|
3
|
+
// escape the , in CN in DN
|
|
4
|
+
function _ldapEscapeDN(s) {
|
|
5
|
+
let ret = "";
|
|
6
|
+
let comaPositions = [];
|
|
7
|
+
let done = false;
|
|
8
|
+
let countEq = 0;
|
|
9
|
+
for (let i = 0; !done && i < s.length; i++) {
|
|
10
|
+
switch (s[i]) {
|
|
11
|
+
case "\\":
|
|
12
|
+
// user already escapped, continue
|
|
13
|
+
i++;
|
|
14
|
+
break;
|
|
15
|
+
case ",":
|
|
16
|
+
if (countEq == 1) {
|
|
17
|
+
comaPositions.push(i);
|
|
18
|
+
}
|
|
19
|
+
break;
|
|
20
|
+
case "=":
|
|
21
|
+
countEq++;
|
|
22
|
+
if (countEq == 2) {
|
|
23
|
+
done = true;
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (done) {
|
|
29
|
+
comaPositions.pop();
|
|
30
|
+
}
|
|
31
|
+
let lastIndex = 0;
|
|
32
|
+
for (let i of comaPositions) {
|
|
33
|
+
ret += s.substring(lastIndex, i);
|
|
34
|
+
ret += "\\,";
|
|
35
|
+
lastIndex = i + 1;
|
|
36
|
+
}
|
|
37
|
+
ret += s.substring(lastIndex);
|
|
38
|
+
return ret;
|
|
39
|
+
}
|
|
3
40
|
|
|
4
41
|
// convert an escaped utf8 string returned from ldapjs
|
|
5
42
|
function _isHex(c) {
|
|
@@ -55,6 +92,7 @@ function _searchResultToUser(pojo) {
|
|
|
55
92
|
}
|
|
56
93
|
// bind and return the ldap client
|
|
57
94
|
function _ldapBind(dn, password, starttls, ldapOpts) {
|
|
95
|
+
dn = _ldapEscapeDN(dn)
|
|
58
96
|
return new Promise(function (resolve, reject) {
|
|
59
97
|
ldapOpts.connectTimeout = ldapOpts.connectTimeout || 5000
|
|
60
98
|
let client = ldap.createClient(ldapOpts)
|
|
@@ -406,7 +444,8 @@ async function authenticate(options) {
|
|
|
406
444
|
options.groupsSearchBase,
|
|
407
445
|
options.groupClass,
|
|
408
446
|
options.groupMemberAttribute,
|
|
409
|
-
options.groupMemberUserAttribute
|
|
447
|
+
options.groupMemberUserAttribute,
|
|
448
|
+
options.attributes
|
|
410
449
|
)
|
|
411
450
|
}
|
|
412
451
|
assert(options.userPassword, 'userPassword must be provided')
|
|
@@ -467,4 +506,5 @@ module.exports.exportForTesting = {
|
|
|
467
506
|
_isHex,
|
|
468
507
|
_parseEscapedHexToUtf8,
|
|
469
508
|
_recursiveParseHexString,
|
|
509
|
+
_ldapEscapeDN
|
|
470
510
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ldap-authentication",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.6",
|
|
4
4
|
"description": "A simple async nodejs library for LDAP user authentication",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -39,6 +39,6 @@
|
|
|
39
39
|
"ldapjs": "^3.0.7"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"jasmine": "^5.
|
|
42
|
+
"jasmine": "^5.3.0"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/test/string.spec.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { exportForTesting } = require('../index.js')
|
|
2
|
-
const { _isHex, _parseEscapedHexToUtf8, _recursiveParseHexString } =
|
|
2
|
+
const { _isHex, _parseEscapedHexToUtf8, _recursiveParseHexString, _ldapEscapeDN } =
|
|
3
3
|
exportForTesting
|
|
4
4
|
|
|
5
5
|
describe('string conversion test', () => {
|
|
@@ -41,3 +41,22 @@ describe('string conversion test', () => {
|
|
|
41
41
|
expect(converted).toEqual(target)
|
|
42
42
|
})
|
|
43
43
|
})
|
|
44
|
+
|
|
45
|
+
describe('escape , in the DN test', ()=>{
|
|
46
|
+
let cases = [
|
|
47
|
+
{ s: "a", want: "a" },
|
|
48
|
+
{ s: "", want: "" },
|
|
49
|
+
{ s: "CN=a,DN=b", want: "CN=a,DN=b" },
|
|
50
|
+
{ s: "CN=a, c,DN=b", want: "CN=a\\, c,DN=b" },
|
|
51
|
+
{ s: "CN=a\\, c,DN=b", want: "CN=a\\, c,DN=b" },
|
|
52
|
+
{ s: "CN=a, b, c,DN=b", want: "CN=a\\, b\\, c,DN=b" },
|
|
53
|
+
{ s: "CN=a, c", want: "CN=a\\, c" },
|
|
54
|
+
]
|
|
55
|
+
for (let c of cases) {
|
|
56
|
+
it("escape "+c.s, ()=>{
|
|
57
|
+
let got = _ldapEscapeDN(c.s)
|
|
58
|
+
expect(got).toEqual(c.want)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
})
|
package/test/test.spec.js
CHANGED
|
@@ -20,6 +20,26 @@ describe('ldap-authentication test', () => {
|
|
|
20
20
|
expect(user).toBeTruthy()
|
|
21
21
|
expect(user.uid).toEqual('gauss')
|
|
22
22
|
})
|
|
23
|
+
it('Use an admin user to check if user exists and return attributes', async () => {
|
|
24
|
+
let options = {
|
|
25
|
+
ldapOpts: {
|
|
26
|
+
url: url,
|
|
27
|
+
},
|
|
28
|
+
adminDn: 'cn=read-only-admin,dc=example,dc=com',
|
|
29
|
+
adminPassword: 'password',
|
|
30
|
+
verifyUserExists: true,
|
|
31
|
+
userSearchBase: 'dc=example,dc=com',
|
|
32
|
+
usernameAttribute: 'uid',
|
|
33
|
+
username: 'gauss',
|
|
34
|
+
attributes: ['uid', 'sn'],
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let user = await authenticate(options)
|
|
38
|
+
expect(user).toBeTruthy()
|
|
39
|
+
expect(user.uid).toEqual('gauss')
|
|
40
|
+
expect(user.sn).toEqual('Bar1')
|
|
41
|
+
expect(user.cn).toBeUndefined()
|
|
42
|
+
})
|
|
23
43
|
it('Use an admin user to authenticate a regular user', async () => {
|
|
24
44
|
let options = {
|
|
25
45
|
ldapOpts: {
|
|
@@ -37,7 +57,7 @@ describe('ldap-authentication test', () => {
|
|
|
37
57
|
expect(user).toBeTruthy()
|
|
38
58
|
expect(user.uid).toEqual('gauss')
|
|
39
59
|
})
|
|
40
|
-
it('Use an admin user to authenticate a regular user and return
|
|
60
|
+
it('Use an admin user to authenticate a regular user and return attributes', async () => {
|
|
41
61
|
let options = {
|
|
42
62
|
ldapOpts: {
|
|
43
63
|
url: url,
|