express-passport-ldap-mongoose
Advanced tools
Comparing version 3.0.2 to 3.1.0
@@ -10,3 +10,3 @@ /* jshint node:true */ | ||
useNewUrlParser: true, | ||
useFindAndModify: false | ||
useFindAndModify: false, | ||
}) | ||
@@ -19,3 +19,2 @@ const session = require('express-session') | ||
const bodyParser = require('body-parser') | ||
const User = require('./model').User | ||
@@ -35,7 +34,7 @@ | ||
secure: false, // this need to be false if https is not used. Otherwise, cookie will not be sent. | ||
} | ||
}, | ||
}) | ||
// The order of the following middleware is very important!! | ||
app.use(bodyParser.json()) | ||
app.use(express.json()) | ||
app.use(sessionMiddleWare) | ||
@@ -54,7 +53,7 @@ // use the library express-passport-ldap-mongoose | ||
ldapOpts: { | ||
url: CONFIG.ldap.url | ||
url: CONFIG.ldap.url, | ||
}, | ||
userDn: `uid={{username}},${CONFIG.ldap.dn}`, | ||
userSearchBase: searchBase, | ||
usernameAttribute: usernameAttr | ||
usernameAttribute: usernameAttr, | ||
} | ||
@@ -69,3 +68,3 @@ let admOptions = { | ||
userSearchBase: searchBase, | ||
usernameAttribute: usernameAttr | ||
usernameAttribute: usernameAttr, | ||
//starttls: true | ||
@@ -80,10 +79,15 @@ } | ||
userSearchBase: searchBase, | ||
usernameAttribute: usernameAttr | ||
usernameAttribute: usernameAttr, | ||
//starttls: true | ||
} | ||
LdapAuth.init(userOptions, '', app, | ||
(id) => User.findOne({ username: id }).exec(), | ||
LdapAuth.initialize( | ||
userOptions, | ||
app, | ||
(id) => User.findOne({ username: id }).exec(), | ||
(user) => { | ||
console.log(`${user[usernameAttr]} has logged in`) | ||
return User.findOneAndUpdate({ username: user[usernameAttr] }, user, { upsert: true, new: true }).exec() | ||
return User.findOneAndUpdate({ username: user[usernameAttr] }, user, { | ||
upsert: true, | ||
new: true, | ||
}).exec() | ||
} | ||
@@ -95,6 +99,5 @@ ) | ||
// Start server | ||
let port=4000 | ||
let port = 4000 | ||
console.log(`server listen on port ${port}`) | ||
app.listen(port, '127.0.0.1') | ||
app.listen(port, '127.0.0.1') |
190
index.js
@@ -9,3 +9,3 @@ /** | ||
var _backwardCompatible = false | ||
var _backwardCompatible = false | ||
var _dn | ||
@@ -19,4 +19,6 @@ var _findFunc | ||
/** | ||
* @deprecated since version 3.0.0. Use initialize() instead | ||
* | ||
* Set up ldap server information, callbacks, and express route. | ||
* | ||
* | ||
* @param {object|string} opt - if is an object, the options object to pass to ldapauth. if is a string, is ldap search base (backward compatible) | ||
@@ -31,6 +33,16 @@ * in opt object, literal `{{username}}` will be replaced with value in req.body.username | ||
*/ | ||
var init = function (opt, ldapurl, router, findFunc, insertFunc, loginUrl, logoutUrl) { | ||
if (typeof(opt) === 'string') { | ||
var init = function ( | ||
opt, | ||
ldapurl, | ||
router, | ||
findFunc, | ||
insertFunc, | ||
loginUrl, | ||
logoutUrl | ||
) { | ||
if (typeof opt === 'string') { | ||
// backward compatible mode | ||
console.log('express-passport-ldap-mongoose: DeprecationWarning: calling init with DN string as first argument will be removed in a future version. Use an option object instead') | ||
console.log( | ||
'express-passport-ldap-mongoose: DeprecationWarning: calling init with DN string as first argument will be removed in a future version. Use an option object instead' | ||
) | ||
_dn = opt | ||
@@ -45,53 +57,56 @@ _backwardCompatible = true | ||
_usernameAttributeName = '' | ||
passport.use('ldap', new CustomStrategy(async (req, done) => { | ||
try { | ||
if (!req.body.username || !req.body.password) { | ||
throw new Error('username and password must be both provided') | ||
} | ||
let username = req.body.username | ||
let password = req.body.password | ||
// construct the parameter to pass in authenticate() function | ||
let options | ||
if (_backwardCompatible) { | ||
_usernameAttributeName = 'uid' | ||
options = { | ||
ldapOpts: { | ||
url: ldapurl | ||
}, | ||
userDn: `uid=${username},${_dn}`, | ||
userPassword: password, | ||
userSearchBase: _dn, | ||
usernameAttribute: 'uid', | ||
username: username | ||
passport.use( | ||
'ldap', | ||
new CustomStrategy(async (req, done) => { | ||
try { | ||
if (!req.body.username || !req.body.password) { | ||
throw new Error('username and password must be both provided') | ||
} | ||
} else { | ||
_usernameAttributeName = opt.usernameAttribute | ||
options = { | ||
ldapOpts: opt.ldapOpts, | ||
userPassword: password, | ||
userSearchBase: opt.userSearchBase, | ||
usernameAttribute: _usernameAttributeName, | ||
username: username, | ||
starttls: opt.starttls | ||
let username = req.body.username | ||
let password = req.body.password | ||
// construct the parameter to pass in authenticate() function | ||
let options | ||
if (_backwardCompatible) { | ||
_usernameAttributeName = 'uid' | ||
options = { | ||
ldapOpts: { | ||
url: ldapurl, | ||
}, | ||
userDn: `uid=${username},${_dn}`, | ||
userPassword: password, | ||
userSearchBase: _dn, | ||
usernameAttribute: 'uid', | ||
username: username, | ||
} | ||
} else { | ||
_usernameAttributeName = opt.usernameAttribute | ||
options = { | ||
ldapOpts: opt.ldapOpts, | ||
userPassword: password, | ||
userSearchBase: opt.userSearchBase, | ||
usernameAttribute: _usernameAttributeName, | ||
username: username, | ||
starttls: opt.starttls, | ||
} | ||
if (opt.userDn) { | ||
options.userDn = opt.userDn.replace('{{username}}', username) | ||
} | ||
if (opt.adminDn) { | ||
options.adminDn = opt.adminDn | ||
} | ||
if (opt.adminPassword) { | ||
options.adminPassword = opt.adminPassword | ||
} | ||
} | ||
if (opt.userDn) { | ||
options.userDn = opt.userDn.replace('{{username}}', username) | ||
} | ||
if (opt.adminDn) { | ||
options.adminDn = opt.adminDn | ||
} | ||
if (opt.adminPassword) { | ||
options.adminPassword = opt.adminPassword | ||
} | ||
// ldap authenticate the user | ||
let user = await authenticate(options) | ||
// success | ||
done(null, user) | ||
} catch (error) { | ||
// authentication failure | ||
done(error, null) | ||
} | ||
// ldap authenticate the user | ||
let user = await authenticate(options) | ||
// success | ||
done(null, user) | ||
} catch (error) { | ||
// authentication failure | ||
done(error, null) | ||
} | ||
})) | ||
}) | ||
) | ||
@@ -102,10 +117,14 @@ passport.serializeUser((user, done) => { | ||
} else { | ||
done('User from ldap server does not have field ' + _usernameAttributeName) | ||
done( | ||
'User from ldap server does not have field ' + _usernameAttributeName | ||
) | ||
} | ||
}) | ||
passport.deserializeUser((id, done) => { | ||
_findFunc(id).then(user => { | ||
_findFunc(id).then((user) => { | ||
if (!user) { | ||
done(new Error(`Deserialize user failed. ${id} is deleted from local DB`)) | ||
done( | ||
new Error(`Deserialize user failed. ${id} is deleted from local DB`) | ||
) | ||
} else { | ||
@@ -122,13 +141,13 @@ done(null, user) | ||
if (err) { | ||
req.logout(); | ||
req.logout() | ||
if (req.originalUrl == _loginUrl) { | ||
next(); // never redirect login page to itself | ||
next() // never redirect login page to itself | ||
} else { | ||
if (req.flash && typeof (req.flash) === "function") { | ||
req.flash("error", err.message); | ||
if (req.flash && typeof req.flash === 'function') { | ||
req.flash('error', err.message) | ||
} | ||
res.redirect(_loginUrl); | ||
res.redirect(_loginUrl) | ||
} | ||
} else { | ||
next(); | ||
next() | ||
} | ||
@@ -139,10 +158,30 @@ }) | ||
router.get(_logoutUrl, function (req, res) { | ||
req.logout(); | ||
res.redirect(_loginUrl); | ||
req.logout() | ||
res.redirect(_loginUrl) | ||
}) | ||
} | ||
/** | ||
* Set up ldap server information, callbacks, and express route. | ||
* | ||
* @param {object} opt - The options object to pass to ldapauth. | ||
* @param {object} router - express router | ||
* @param {function} findFunc - function(id) to find the user in local db by id | ||
* @param {function} insertFunc - function(user) to upsert user into local db | ||
* @param {string} [loginUrl] - path to login page. Default: /login | ||
* @param {string} [logoutUrl] - path to logout page. Default: /logout | ||
*/ | ||
var initialize = function ( | ||
opt, | ||
router, | ||
findFunc, | ||
insertFunc, | ||
loginUrl, | ||
logoutUrl | ||
) { | ||
return init(opt, '', router, findFunc, insertFunc, loginUrl, logoutUrl) | ||
} | ||
/** | ||
* Customized login authentication handler to send {success: true} | ||
* Customized login authentication handler to send {success: true} | ||
* on successful authenticate, or {success: false} on failed authenticate | ||
@@ -153,3 +192,3 @@ */ | ||
if (err) { | ||
res.status(401).json({success: false, message: err.message}) | ||
res.status(401).json({ success: false, message: err.message }) | ||
return | ||
@@ -160,9 +199,14 @@ } | ||
} else { | ||
req.login(user, loginErr => { | ||
req.login(user, (loginErr) => { | ||
if (loginErr) { | ||
return next(loginErr); | ||
return next(loginErr) | ||
} | ||
_insertFunc(user).then(user => { | ||
var userObj = typeof(user.toObject) === "function" ? user.toObject(): user | ||
return res.json({ success: true, message: 'authentication succeeded', user: userObj }) | ||
_insertFunc(user).then((user) => { | ||
var userObj = | ||
typeof user.toObject === 'function' ? user.toObject() : user | ||
return res.json({ | ||
success: true, | ||
message: 'authentication succeeded', | ||
user: userObj, | ||
}) | ||
}) | ||
@@ -174,3 +218,3 @@ }) | ||
module.exports.init = init | ||
module.exports.initialize = initialize |
{ | ||
"name": "express-passport-ldap-mongoose", | ||
"version": "3.0.2", | ||
"version": "3.1.0", | ||
"description": "A library to use passport-ldapauth and local MongoDB to authenticate and save users", | ||
@@ -10,3 +10,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"ldap-authentication": "^2.2.1", | ||
"ldap-authentication": "^2.2.7", | ||
"passport": "^0.4.1", | ||
@@ -16,7 +16,7 @@ "passport-custom": "^1.1.1" | ||
"devDependencies": { | ||
"body-parser": "^1.19.0", | ||
"connect-mongo": "^3.2.0", | ||
"express": "^4.17.1", | ||
"express-session": "^1.17.1", | ||
"jest": "^26.0.1", | ||
"jasmine": "^3.7.0", | ||
"jasmine-console-reporter": "^3.1.0", | ||
"mongoose": "^5.9.18", | ||
@@ -27,4 +27,4 @@ "superagent": "^5.2.2", | ||
"scripts": { | ||
"test": "jest test/test.js" | ||
"test": "node test/jasmine.js" | ||
} | ||
} |
@@ -32,12 +32,17 @@ # express-passport-ldap-mongoose | ||
`express-passport-ldap-mongoose` configures passportjs and adds the login and logout route to | ||
your express app or router. All you need to do is call the `init` function of the library | ||
your express app or router. All you need to do is call the `initialize` function of the library | ||
and everything else is taken care of. | ||
```javascript | ||
const LdapAuth = require('express-passport-ldap-mongoose') | ||
app.use(bodyParser.json()) | ||
app.use(express.json()) | ||
app.use(sessionMiddleWare) | ||
LdapAuth.init(options, '', app, findUserFunc, upsertUserFunc, loginPath, logoutPath) | ||
LdapAuth.initialize(options, app, findUserFunc, upsertUserFunc, loginPath, logoutPath) | ||
``` | ||
> Since version 3.1.0, you can still use `init()` but it is deprecated. | ||
Use `initialize()` instead which is simpler. | ||
## MongoDB model | ||
@@ -79,5 +84,2 @@ | ||
* `ldapurl` (deprecated): URL of LDAP server. Example: `ldaps://ldap.example.com`, `ldap://ldap.example.com` | ||
It will be ignored if the first parameter of the function is an object | ||
* `app`: Express app or router | ||
@@ -114,3 +116,2 @@ * `findUserFunc`: `function(id)`. A function takes a string id and return a promise that resolves to a user or null. | ||
const bodyParser = require('body-parser') | ||
const User = require('./model').User | ||
@@ -134,21 +135,23 @@ | ||
// The order of the following middleware is very important!! | ||
app.use(bodyParser.json()) | ||
app.use(express.json()) | ||
app.use(sessionMiddleWare) | ||
// use the library express-passport-ldap-mongoose | ||
let usernameAttributeName = 'uid' | ||
LdapAuth.init({ | ||
ldapOpts: { | ||
url: 'ldap://localhost' | ||
}, | ||
// note in this example it only use the user to directly | ||
// bind to the LDAP server. You can also use an admin | ||
// here. See the document of ldap-authentication. | ||
userDn: `uid={{username}},${ldapBaseDn}`, | ||
userSearchBase: ldapBaseDn, | ||
usernameAttribute: usernameAttributeName | ||
}, '', app, (id) => { | ||
return User.findOne({ usernameAttributeName: id }).exec() | ||
}, (user) => { | ||
return User.findOneAndUpdate({ username: user[usernameAttributeName] }, user, { upsert: true, new: true }).exec() | ||
}) | ||
LdapAuth.initialize({ | ||
ldapOpts: { | ||
url: 'ldap://localhost' | ||
}, | ||
// note in this example it only use the user to directly | ||
// bind to the LDAP server. You can also use an admin | ||
// here. See the document of ldap-authentication. | ||
userDn: `uid={{username}},${ldapBaseDn}`, | ||
userSearchBase: ldapBaseDn, | ||
usernameAttribute: usernameAttributeName | ||
}, | ||
app, | ||
(id) => { | ||
return User.findOne({ usernameAttributeName: id }).exec() | ||
}, (user) => { | ||
return User.findOneAndUpdate({ username: user[usernameAttributeName] }, user, { upsert: true, new: true }).exec() | ||
}) | ||
@@ -155,0 +158,0 @@ // serve static pages (where login.html resides) |
138
test/test.js
@@ -1,2 +0,2 @@ | ||
const request = require('supertest'); | ||
const request = require('supertest') | ||
const auth = require('../index.js') | ||
@@ -8,22 +8,20 @@ | ||
const bodyParser = require('body-parser') | ||
var sessionMiddleWare = session({ | ||
secret: "test", | ||
resave: true, | ||
saveUninitialized: true, | ||
unset: 'destroy', | ||
cookie: { | ||
httpOnly: false, | ||
maxAge: 1000 * 3600 * 24, | ||
secure: false, // this need to be false if https is not used. Otherwise, cookie will not be sent. | ||
} | ||
secret: 'test', | ||
resave: true, | ||
saveUninitialized: true, | ||
unset: 'destroy', | ||
cookie: { | ||
httpOnly: false, | ||
maxAge: 1000 * 3600 * 24, | ||
secure: false, // this need to be false if https is not used. Otherwise, cookie will not be sent. | ||
}, | ||
}) | ||
// The order of the following middleware is very important!! | ||
app.use(bodyParser.json()) | ||
app.use(express.json()) | ||
app.use(sessionMiddleWare) | ||
app.get('/login', (req, res) => { | ||
res.json({ success: true }) | ||
res.json({ success: true }) | ||
}) | ||
@@ -33,70 +31,64 @@ | ||
var User = [] | ||
function findUserById(id) { | ||
return new Promise((resolve, reject) => { | ||
return resolve(User.find(u => { return u.uid === id })) | ||
}) | ||
async function findUserById(id) { | ||
return User.find((u) => u.uid === id) | ||
} | ||
function upsertUser(user) { | ||
return new Promise((resolve, reject) => { | ||
var existingUser = User.find(u => { | ||
return u.uid === user.uid | ||
}) | ||
if (!existingUser) User.push(user) | ||
return resolve(user) | ||
}) | ||
async function upsertUser(user) { | ||
let existingUser = User.find((u) => u.uid === user.uid) | ||
if (!existingUser) User.push(user) | ||
return user | ||
} | ||
let userOptions = { | ||
ldapOpts: { | ||
url: 'ldap://ldap.forumsys.com' | ||
}, | ||
userDn: `uid={{username}},dc=example,dc=com`, | ||
userSearchBase: 'dc=example,dc=com', | ||
usernameAttribute: 'uid' | ||
ldapOpts: { | ||
url: 'ldap://ldap.forumsys.com', | ||
}, | ||
userDn: `uid={{username}},dc=example,dc=com`, | ||
userSearchBase: 'dc=example,dc=com', | ||
usernameAttribute: 'uid', | ||
} | ||
auth.init(userOptions, '', app, | ||
findUserById, upsertUser | ||
) | ||
auth.initialize(userOptions, app, findUserById, upsertUser) | ||
describe('Test ldap authenticate', () => { | ||
test('It should response the GET method', () => { | ||
return request(app).get("/login").then(response => { | ||
expect(response.statusCode).toBe(200) | ||
}) | ||
it('It should response the GET method', async () => { | ||
let response = await request(app).get('/login') | ||
expect(response.statusCode).toBe(200) | ||
}) | ||
it('It should response the POST method', async () => { | ||
let response = await request(app).post('/login') | ||
expect(response.statusCode).toBe(401) | ||
expect(response.body.success).toBeFalsy() | ||
expect(response.body.message).toEqual( | ||
'username and password must be both provided' | ||
) | ||
}) | ||
it('invalid username/password result', async () => { | ||
let response = await request(app) | ||
.post('/login') | ||
.type('json') | ||
.send({ username: 'gauss', password: 'bbb' }) | ||
expect(response.statusCode).toBe(401) | ||
expect(response.body.success).toBeFalsy() | ||
expect(response.body.message).toEqual('Invalid Credentials') | ||
expect(response.body.user).toBeUndefined() | ||
let user = User.find((u) => { | ||
return u.username === 'gauss' | ||
}) | ||
test('It should response the POST method', () => { | ||
return request(app).post("/login").then(response => { | ||
expect(response.statusCode).toBe(401) | ||
expect(response.body.success).toBeFalsy() | ||
expect(response.body.message).toEqual("username and password must be both provided") | ||
}) | ||
expect(user).toBeUndefined() | ||
}) | ||
it('correct username/password result', async () => { | ||
let response = await request(app) | ||
.post('/login') | ||
.type('json') | ||
.send({ username: 'gauss', password: 'password' }) | ||
expect(response.statusCode).toBe(200) | ||
expect(response.body.success).toBeTruthy() | ||
expect(response.body.message).toBe('authentication succeeded') | ||
expect(response.body.user.uid).toBe('gauss') | ||
let user = User.find((u) => { | ||
return u.uid === 'gauss' | ||
}) | ||
test('invalid username/password result', () => { | ||
return request(app).post("/login") | ||
.type('json') | ||
.send({ username: 'gauss', password: 'bbb' }) | ||
.then(response => { | ||
expect(response.statusCode).toBe(401) | ||
expect(response.body.success).toBeFalsy() | ||
expect(response.body.message).toEqual("Invalid Credentials") | ||
expect(response.body.user).toBeUndefined() | ||
user = User.find(u => { return u.username === "gauss" }) | ||
expect(user).toBeUndefined() | ||
}) | ||
}) | ||
test('correct username/password result', () => { | ||
return request(app).post("/login") | ||
.type('json') | ||
.send({ username: 'gauss', password: 'password' }) | ||
.then(response => { | ||
expect(response.statusCode).toBe(200) | ||
expect(response.body.success).toBeTruthy() | ||
expect(response.body.message).toBe('authentication succeeded') | ||
expect(response.body.user.uid).toBe('gauss') | ||
user = User.find(u => { return u.uid === "gauss" }) | ||
expect(user).toBeDefined() | ||
}) | ||
}) | ||
}) | ||
expect(user).toBeDefined() | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
24925
14
467
161
Updatedldap-authentication@^2.2.7