mirror of
https://github.com/hanzoai/passport-ldapauth.git
synced 2026-09-23 23:50:02 +00:00
Better JSDoc and other linter errors fixed
Disabled no-invalid-this since this is now very much bind based
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"valid-jsdoc": ["error"],
|
||||
"require-jsdoc": ["error"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "never"],
|
||||
"default-case": ["error"],
|
||||
"guard-for-in": ["error"],
|
||||
"no-caller": ["error"],
|
||||
"no-empty-function": ["error"],
|
||||
"no-eval": ["error"],
|
||||
"no-extend-native": ["error"],
|
||||
"no-extra-bind": ["error"],
|
||||
"no-floating-decimal": ["error"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-labels": ["error"],
|
||||
"no-lone-blocks": ["error"],
|
||||
"no-loop-func": ["error"],
|
||||
"no-param-reassign": ["error"],
|
||||
"no-restricted-properties": ["error"],
|
||||
"no-return-assign": ["error"],
|
||||
"no-self-compare": ["error"],
|
||||
"no-sequences": ["error"],
|
||||
"no-throw-literal": ["error"],
|
||||
"no-unmodified-loop-condition": ["error"],
|
||||
"no-unused-expressions": ["error", { "allowShortCircuit": true }],
|
||||
"no-useless-call": ["error"],
|
||||
"no-useless-concat": ["error"],
|
||||
"no-useless-escape": ["error"],
|
||||
"no-void": ["error"],
|
||||
"no-with": ["error"],
|
||||
"radix": ["error", "always"],
|
||||
"no-catch-shadow": ["error"],
|
||||
"no-shadow": ["error"],
|
||||
"no-shadow-restricted-names": ["error"],
|
||||
"no-use-before-define": ["error"],
|
||||
"callback-return": ["error"],
|
||||
"global-require": ["error"],
|
||||
"no-mixed-requires": ["error"],
|
||||
"handle-callback-err": ["error"],
|
||||
"no-new-require": ["error"],
|
||||
"no-path-concat": ["error"],
|
||||
"no-process-exit": ["error"],
|
||||
"array-bracket-spacing": ["error", "never"],
|
||||
"block-spacing": ["error", "always"],
|
||||
"brace-style": ["error"],
|
||||
"camelcase": ["error"],
|
||||
"comma-dangle": ["error", "never"],
|
||||
"comma-spacing": ["error", { "before": false, "after": true }],
|
||||
"comma-style": ["error", "last"],
|
||||
"eol-last": ["error"],
|
||||
"func-call-spacing": ["error", "never"],
|
||||
"key-spacing": ["error", { "beforeColon": false }],
|
||||
"keyword-spacing": ["error", { "before": true }],
|
||||
"new-parens": ["error"],
|
||||
"no-bitwise": ["error"],
|
||||
"no-mixed-operators": ["error"],
|
||||
"no-trailing-spaces": ["error"],
|
||||
"one-var": ["error", "never"],
|
||||
"one-var-declaration-per-line": ["error"],
|
||||
"space-in-parens": ["error", "never"],
|
||||
"space-infix-ops": ["error"],
|
||||
"spaced-comment": ["error", "always"],
|
||||
"curly": ["error"]
|
||||
}
|
||||
}
|
||||
@@ -2,3 +2,4 @@ node_modules
|
||||
npm-debug.log
|
||||
.directory
|
||||
.idea/
|
||||
out
|
||||
|
||||
@@ -1,50 +1,109 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
var passport = require('passport-strategy');
|
||||
var LdapAuth = require('ldapauth-fork');
|
||||
var util = require('util');
|
||||
|
||||
/**
|
||||
* Passport wrapper for ldapauth
|
||||
*/
|
||||
var passport = require('passport-strategy'),
|
||||
LdapAuth = require('ldapauth-fork'),
|
||||
util = require('util');
|
||||
|
||||
|
||||
/**
|
||||
* Options callback callback (ie. the callback given if giving a callback
|
||||
* for options instead of an object)
|
||||
*
|
||||
* @callback optionsCallbackCallback
|
||||
* @param {(Error|undefined)} err - Possible error
|
||||
* @param {Object} options - Options object
|
||||
*/
|
||||
/**
|
||||
* Options callback
|
||||
*
|
||||
* @callback optionsCallback
|
||||
* @param {Object} req - HTTP request
|
||||
* @param {optionsCallbackCallback} callback - The callback returning the options
|
||||
*/
|
||||
/**
|
||||
* Verify done callback
|
||||
*
|
||||
* @callback verifyDoneCallback
|
||||
* @param {(Error|undefined)} err - Possible error
|
||||
* @param {(Object|boolean)} user - The verified user or false if not allowed
|
||||
* @param {Object} [info] info - Additional info message
|
||||
*/
|
||||
/**
|
||||
* Found LDAP user verify callback
|
||||
*
|
||||
* @callback verifyCallback
|
||||
* @param {Object} user - The user object from LDAP
|
||||
* @param {verifyDoneCallback} callback - The verify callback
|
||||
*/
|
||||
/**
|
||||
* Found LDAP user verify callback with request
|
||||
*
|
||||
* @callback verifyReqCallback
|
||||
* @param {Object} req - The HTTP request
|
||||
* @param {Object} user - The user object from LDAP
|
||||
* @param {verifyDoneCallback} callback - The verify callback
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add default values to options
|
||||
*
|
||||
* @private
|
||||
* @param {Object} options - Options object
|
||||
* @returns {Object} The given options with defaults filled
|
||||
*/
|
||||
var setDefaults = function(options) {
|
||||
options.usernameField || (options.usernameField = 'username');
|
||||
options.passwordField || (options.passwordField = 'password');
|
||||
return options;
|
||||
};
|
||||
|
||||
/**
|
||||
* Strategy constructor
|
||||
* <br>
|
||||
*
|
||||
* The LDAP authentication strategy authenticates requests based on the
|
||||
* credentials submitted through an HTML-based login form.
|
||||
* <br>
|
||||
*
|
||||
* Applications may supply a `verify` callback which accepts `user` object
|
||||
* and then calls the `done` callback supplying a `user`, which should be set
|
||||
* to `false` if user is not allowed to authenticate. If an exception occured,
|
||||
* `err` should be set.
|
||||
*
|
||||
* Options:
|
||||
* - `server` options for ldapauth, see https://github.com/trentm/node-ldapauth
|
||||
* - `usernameField` field name where the username is found, defaults to _username_
|
||||
* - `passwordField` field name where the password is found, defaults to _password_
|
||||
* - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
|
||||
* <br>
|
||||
*
|
||||
* Options can be also given as function that accepts a callback end calls it
|
||||
* with error and options arguments. Notice that the callback is executed on
|
||||
* every authenticate call.
|
||||
* <br>
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var LdapStrategy = require('passport-ldapauth').Strategy;
|
||||
* passport.use(new LdapStrategy({
|
||||
* server: {
|
||||
* url: 'ldap://localhost:389',
|
||||
* bindDn: 'cn=root',
|
||||
* bindCredentials: 'secret',
|
||||
* searchBase: 'ou=passport-ldapauth',
|
||||
* searchFilter: '(uid={{username}})',
|
||||
* reconnect: true
|
||||
* }
|
||||
* },
|
||||
* function(user, done) {
|
||||
* return cb(null, user);
|
||||
* }
|
||||
* ));
|
||||
* <pre>
|
||||
* var LdapStrategy = require('passport-ldapauth').Strategy;
|
||||
* passport.use(new LdapStrategy({
|
||||
* server: {
|
||||
* url: 'ldap://localhost:389',
|
||||
* bindDN: 'cn=root',
|
||||
* bindCredentials: 'secret',
|
||||
* searchBase: 'ou=passport-ldapauth',
|
||||
* searchFilter: '(uid={{username}})',
|
||||
* reconnect: true
|
||||
* }
|
||||
* },
|
||||
* function(user, done) {
|
||||
* return cb(null, user);
|
||||
* }
|
||||
* ));
|
||||
* </pre>
|
||||
* @constructor
|
||||
* @param {(Object|optionsCallback)} options - Configuration options or options returning function
|
||||
* @param {(Object)} options.server - [ldapauth-fork options]{@link https://github.com/vesse/node-ldapauth-fork}
|
||||
* @param {(string)} [options.usernameField=username] - Form field name for username
|
||||
* @param {(string)} [options.passwordField=password] - Form field name for password
|
||||
* @param {(boolean)} [options.passReqToCallback=false] - If true, request is passed to verify callback
|
||||
* @param {(verifyCallback|verifyReqCallback|undefined)} [verify] - User verify callback
|
||||
*/
|
||||
var Strategy = function(options, verify) {
|
||||
// We now accept function as options as well so we cannot assume anymore
|
||||
@@ -71,23 +130,17 @@ var Strategy = function(options, verify) {
|
||||
|
||||
util.inherits(Strategy, passport.Strategy);
|
||||
|
||||
/**
|
||||
* Add default values to options
|
||||
*
|
||||
* @param options
|
||||
* @returns {*}
|
||||
*/
|
||||
var setDefaults = function(options) {
|
||||
options.usernameField || (options.usernameField = 'username');
|
||||
options.passwordField || (options.passwordField = 'password');
|
||||
return options;
|
||||
};
|
||||
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Get value for given field from given object. Taken from passport-local,
|
||||
* copyright 2011-2013 Jared Hanson
|
||||
*
|
||||
* @private
|
||||
* @param {Object} obj - The HTTP request object
|
||||
* @param {string} field - The field name to look for
|
||||
* @returns {string|null} - Found value for the field or null
|
||||
*/
|
||||
var lookup = function (obj, field) {
|
||||
var lookup = function(obj, field) {
|
||||
var i, len, chain, prop;
|
||||
if (!obj) { return null; }
|
||||
chain = field.split(']').join('').split('[');
|
||||
@@ -99,24 +152,36 @@ var lookup = function (obj, field) {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
||||
/**
|
||||
* Verify the outcome of caller verify function - even if authentication (and
|
||||
* usually authorization) is taken care by LDAP there may be reasons why
|
||||
* a verify callback is provided, and again reasons why it may reject login
|
||||
* for a valid user.
|
||||
*
|
||||
* @private
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var verify = function() {
|
||||
// Callback given to user given verify function.
|
||||
return function(err, user, info) {
|
||||
if (err) return this.error(err);
|
||||
if (!user) return this.fail(info);
|
||||
if (err) {
|
||||
return this.error(err);
|
||||
}
|
||||
if (!user) {
|
||||
return this.fail(info);
|
||||
}
|
||||
return this.success(user, info);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute failureErrorCallback if provided
|
||||
*
|
||||
* @private
|
||||
* @param {Error} err - The error occurred
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var handleErrorAsFailure = function(err) {
|
||||
if (typeof this.options.failureErrorCallback === 'function') {
|
||||
@@ -126,20 +191,19 @@ var handleErrorAsFailure = function(err) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Options (passed when calling `passport.authenticate()`):
|
||||
* - `badRequestMessage` flash message for missing username/password
|
||||
* (default: 'Missing credentials')
|
||||
* - `invalidCredentials` flash message for InvalidCredentialsError, NoSuchObjectError,
|
||||
* and /no such user/ LDAP errors
|
||||
* (default: 'Invalid username/password')
|
||||
* - `userNotFound` flash message when LDAP returns no error but also no user
|
||||
* (default: 'Invalid username/password')
|
||||
* - `constraintViolation` flash message when user account is locked
|
||||
* (default: 'Exceeded password retry limit, account locked')
|
||||
* The actual authenticate implementation
|
||||
*
|
||||
* @private
|
||||
* @param {Object} req - The HTTP request
|
||||
* @param {Object} [options] - Flash messages
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var handleAuthentication = function(req, options) {
|
||||
var username, password, ldap, errorHandler;
|
||||
options || (options = {});
|
||||
var username;
|
||||
var password;
|
||||
var ldap;
|
||||
var errorHandler;
|
||||
options || (options = {}); // eslint-disable-line no-param-reassign
|
||||
|
||||
if (typeof this.options.credentialsLookup === 'function') {
|
||||
var credentials = this.options.credentialsLookup(req);
|
||||
@@ -155,7 +219,7 @@ var handleAuthentication = function(req, options) {
|
||||
}
|
||||
|
||||
if (!username || !password) {
|
||||
return this.fail({message: options.badRequestMessage || 'Missing credentials'}, 400);
|
||||
return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400);
|
||||
}
|
||||
|
||||
errorHandler = this.options.handleErrorsAsFailures === true ? handleErrorAsFailure.bind(this) : this.error.bind(this);
|
||||
@@ -179,30 +243,34 @@ var handleAuthentication = function(req, options) {
|
||||
ldap = new LdapAuth(this.options.server);
|
||||
ldap.on('error', errorHandler);
|
||||
ldap.authenticate(username, password, function(err, user) {
|
||||
ldap.close(function(){}); // We don't care about the closing
|
||||
ldap.close(function(){
|
||||
// We don't care about the closing
|
||||
});
|
||||
|
||||
if (err) {
|
||||
// Invalid credentials / user not found are not errors but login failures
|
||||
if (err.name === 'InvalidCredentialsError' || err.name === 'NoSuchObjectError' || (typeof err === 'string' && err.match(/no such user/i))) {
|
||||
var message = options.invalidCredentials || 'Invalid username/password';
|
||||
|
||||
if(err.message) {
|
||||
if (err.message) {
|
||||
var ldapComment = err.message.match(/data ([0-9a-fA-F]*), v[0-9a-fA-F]*/);
|
||||
if(ldapComment && ldapComment[1]){
|
||||
if (ldapComment && ldapComment[1]){
|
||||
message = messages[ldapComment[1]] || messages['default'];
|
||||
}
|
||||
}
|
||||
return this.fail({message: message}, 401);
|
||||
return this.fail({ message: message }, 401);
|
||||
}
|
||||
if (err.name === 'ConstraintViolationError'){
|
||||
return this.fail({message: options.constraintViolation || 'Exceeded password retry limit, account locked'}, 401);
|
||||
return this.fail({ message: options.constraintViolation || 'Exceeded password retry limit, account locked' }, 401);
|
||||
}
|
||||
|
||||
// Other errors are (most likely) real errors
|
||||
return errorHandler(err);
|
||||
}
|
||||
|
||||
if (!user) return this.fail({message: options.userNotFound || 'Invalid username/password'}, 401);
|
||||
if (!user) {
|
||||
return this.fail({ message: options.userNotFound || 'Invalid username/password' }, 401);
|
||||
}
|
||||
|
||||
// Execute given verify function
|
||||
if (this.verify) {
|
||||
@@ -219,6 +287,22 @@ var handleAuthentication = function(req, options) {
|
||||
|
||||
/**
|
||||
* Authenticate the request coming from a form or such.
|
||||
*
|
||||
* @param {Object} req - The HTTP request
|
||||
* @param {Object} [options] - Authentication options (flash messages). All messages have default values.
|
||||
* @param {string} [options.badRequestMessage] - Message for missing username/password
|
||||
* @param {string} [options.invalidCredentials] - Message for InvalidCredentialsError, NoSuchObjectError, and /no such user/ LDAP errors
|
||||
* @param {string} [options.userNotFound] - Message for user not found
|
||||
* @param {string} [options.constraintViolation] - Message when account is locked (or other constraint violation)
|
||||
* @param {string} [options.invalidLogonHours] - Message for Windows AD invalidLogonHours error
|
||||
* @param {string} [options.invalidWorkstation] - Message for Windows AD invalidWorkstation error
|
||||
* @param {string} [options.passwordExpired] - Message for Windows AD passwordExpired error
|
||||
* @param {string} [options.accountDisabled] - Message for Windows AD accountDisabled error
|
||||
* @param {string} [options.accountDisabled] - Message for Windows AD accountDisabled error
|
||||
* @param {string} [options.accountExpired] - Message for Windows AD accountExpired error
|
||||
* @param {string} [options.passwordMustChange] - Message for Windows AD passwordMustChange error
|
||||
* @param {string} [options.accountLockedOut] - Message for Windows AD accountLockedOut error
|
||||
* @returns {undefined}
|
||||
*/
|
||||
Strategy.prototype.authenticate = function(req, options) {
|
||||
if ((typeof this.options === 'object') && (!this.getOptions)) {
|
||||
@@ -226,14 +310,16 @@ Strategy.prototype.authenticate = function(req, options) {
|
||||
}
|
||||
|
||||
var callback = function(err, configuration) {
|
||||
if (err) return this.fail(err);
|
||||
if (err) {
|
||||
return this.fail(err);
|
||||
}
|
||||
|
||||
this.options = setDefaults(configuration);
|
||||
handleAuthentication.call(this, req, options);
|
||||
};
|
||||
|
||||
// Added functionality: getOptions can accept now up to 2 parameters
|
||||
if (this.getOptions.length ===1) { // Accepts 1 parameter, backwards compatibility
|
||||
if (this.getOptions.length === 1) { // Accepts 1 parameter, backwards compatibility
|
||||
this.getOptions(callback.bind(this));
|
||||
} else { // Accepts 2 parameters, pass request as well
|
||||
this.getOptions(req, callback.bind(this));
|
||||
|
||||
+15
-10
@@ -30,20 +30,25 @@
|
||||
"url": "https://github.com/vesse/passport-ldapauth/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"passport-strategy": "1.x.x",
|
||||
"ldapauth-fork": "~3.0.0"
|
||||
"passport-strategy": "^1.0.0",
|
||||
"ldapauth-fork": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"basic-auth": "1.1.x",
|
||||
"body-parser": "1.15.x",
|
||||
"chai": "3.5.x",
|
||||
"express": "4.14.x",
|
||||
"ldapjs": "1.0.x",
|
||||
"mocha": "3.2.x",
|
||||
"passport": "0.3.x",
|
||||
"supertest": "2.0.x"
|
||||
"basic-auth": "^1.1.0",
|
||||
"body-parser": "^1.17.2",
|
||||
"chai": "^4.0.1",
|
||||
"eslint": "^3.19.0",
|
||||
"express": "^4.15.3",
|
||||
"ldapjs": "^1.0.1",
|
||||
"mocha": "^3.4.2",
|
||||
"passport": "^0.3.2",
|
||||
"supertest": "^3.0.0",
|
||||
"watch": "^1.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "npm run lint",
|
||||
"lint": "eslint ./lib",
|
||||
"lint:watch": "watch 'npm run lint' ./lib --wait 0.5",
|
||||
"test": "NODE_PATH=lib mocha --reporter spec test/*-test.js"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user