6

I am trying to authenticate openLDAP username and password using passport-ldapauth npm. While executing the below code I am always getting error as { message: 'Missing credentials' }. Kindly help me what is wrong with my code.

var connect = require('connect'),
    app = connect(),
    passport = require('passport'),
    LdapStrategy = require('passport-ldapauth');

// Credentials from the free LDAP test server by forumsys
// More info at: http://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
var OPTS = {
    server: {
        url: 'ldap://<ip>',
        bindDn: '<admin username>',
        bindCredentials: '<admin password>',
        usernameField: "<passing actual username>",
        passwordField: "<password>"
    }
};

passport.use(new LdapStrategy(OPTS));

app.use(passport.initialize());


app.use(connectRoute(function (router) {
        router.post('/login', function (req, res, next) {
            passport.authenticate('ldapauth', {session: false}, function (err, user, info) {
                console.log(info);
                if (err) {
                    return next(err); // will generate a 500 error
                }
                // Generate a JSON response reflecting authentication status
                if (!user) {
                    return res.send({success: false, message: 'authentication failed'});
                }
                return res.send({success: true, message: 'authentication succeeded'});
            })(req, res, next);
        });
    }))

app.listen(8080);

For more details, please see this badRequestMessage flash message for missing username/password (default: 'Missing credentials')

user4324324
  • 559
  • 3
  • 7
  • 25
  • Are the values in your OPTS object actually what appear above, or did you remove them for this post? – HeadCode Jun 09 '15 at 00:07
  • @HeadCode I have removed the actual values for this post – user4324324 Jun 09 '15 at 02:58
  • 3
    I've been looking at passport-ldapauth as well but I'd say that the documentation is good only if you really understand how to use it already. You might check out this post: http://stackoverflow.com/questions/28159093/ldap-authentication-with-nodejs-express-and-passport-ldapauth. For one thing, it looks like you're supplying usernames and passwords where you should just be supplying the form field names for those things. – HeadCode Jun 09 '15 at 05:11
  • @HeadCode as per the documentation given in https://www.npmjs.com/package/passport-ldapauth, I tried the Express example which gives me error "Missing Credentials" – user4324324 Jun 09 '15 at 08:22
  • I haven't had time to delve into this but I am really interested to hear if you found the solution. Please post it if you did! – HeadCode Jun 11 '15 at 15:46

9 Answers9

8

Here is my configuration:

var passport = require('passport');
var LdapStrategy = require('passport-ldapauth').Strategy;

var OPTS = {
  server: {
    url: '<ldap server>',
    bindDn: '<admin username>',
    bindCredentials: '<admin password>',
    searchBase: '<base dn>',
    searchFilter: '(sAMAccountName={{username}})'
  }
};

passport.use(new LdapStrategy(OPTS));

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function(user, done) {
  done(null, user);
});

passport.deserializeUser(function(user, done) {
  done(null, user);
});

The usernameField and passwordField in OPTS are optional. My program is using the default value username and password. If the usernameField is set, you need to modify searchFilter as (sAMAccountName={{<usernameField value>}}) or (uid={{<usernameField value>}}).

Also, in order to store the login status in your session, express-session module is required. The session configuration is like:

var session = require('express-session');
app.use(session({
  secret: 'ldap secret',
  resave: false,
  saveUninitialized: true,
  cookie : { httpOnly: true, maxAge: 2419200000 } /// maxAge in milliseconds
}));

Then, you can use the LDAP authentication as:

app.post('/login', passport.authenticate('ldapauth', {
  successRedirect: '/users/profile', failureRedirect: '/login'
})); 
G Chen
  • 199
  • 3
  • 12
  • "My program is using the default value username and password. If the `usernameField` is set, you need to modify searchFilter as `(sAMAccountName={{}})` or `(uid={{}})`." Could you give an example for this? For instance, if I search for the user "test", should the `usernameField` be "test"? – Heathcliff Aug 02 '16 at 13:29
  • 1
    @Heathcliff No, `usernameField` and `passwordField` are the login form fields' names. If your login page HTML contains eg. `` you would set `usernameField` to `weirdusernamefield`. User enters the username (eg. `test`) to the login form, and the strategy knows to look for `weirdusernamefield` value which is then used for LDAP search and bind. – vesse Aug 03 '16 at 20:48
1

According to the documentation provided by passport-ldapauth, the object which is the value of server does not contain the usernameField and passwordField. Your strategy should look like:

var OPTS = {
  server: {
    url: 'ldap://<ip>',
    bindDn: '<admin username>',
    bindCredentials: '<admin password>'
  },
  usernameField: "<field containing username>",
  passwordField: "<field containing password>"
};

But as G Chen mentions in his answer, the usernameField and passwordField are optional.

warun26
  • 453
  • 9
  • 18
1

Please check the following Code where Basic Authentication of the user has to be performed. This code works when a user login credentials have to be verified.

We need to use 3 fields viz. usernameField, passwordField and credentialsLookup

`var basicAuth = require('basic-auth');
var OPTS = {
server: {
url: Constants.LDAP_SERVER_URL_STRING,
bindDn: Constants.LDAP_ADMIN_STRING, 
bindCredentials: Constants.LDAP_PASSWORD_STRING,
// searchBase: Constants.LDAP_SEARCHBASE_STRING,
// searchFilter: Constants.LDAP_SEARCHFILTER_STRING
//          reconnect: true

},
usernameField: username,
passwordField: password,
credentialsLookup: basicAuth
};

LDAP Administration tools like Userbooster light are very useful in understanding how the authentication process happens.

Fields such as searchBase, searchFilter are of no use. The disclaimer however is that you need to test to see if it is true

1
var basicAuth = require('basic-auth');
var LdapAuth = require('ldapauth-fork');
var username: string = req.body.username;
var password: string = req.body.password;

var ldap = new LdapAuth({
   url:                Constants.LDAP_SERVER_URL_STRING,
   bindDN:             Constants.LDAP_BIND_DN_STRING,
   bindCredentials:    Constants.LDAP_PASSWORD_STRING,
   searchBase:         'uid=' + username + ',' + Constants.LDAP_SEARCHBASE_STRING,
   searchFilter:       Constants.LDAP_SEARCHFILTER_STRING
   //  reconnect: true
});    

ldap.authenticate(username, password, function(err, user) {  
   if (err) {     
       console.log("login Error");   
       res.send({ success : false, message : 'authentication failed' });
   } else if(!user.uid) {
      console.log("user not found Error");
      res.send({ success : false, message : 'authentication failed' });
   } else if(user.uid) {
      console.log("success : user "+ user.uid +" found ");
   }
});
mjk
  • 2,443
  • 4
  • 33
  • 33
  • i have an issue about this approach https://stackoverflow.com/questions/51763457/ldapauth-fork-invalidcredentialserror – MuhanadY Aug 09 '18 at 11:06
0

Maybe the issue is not caused by the passport-ldapauth. There may be some problems with your post requests. Check if there are [usernameField], [passwordField] in your request before using passport.authenticate.

ruichao
  • 21
  • 2
0

Please check NPM with "LDAP Authentication"

You will come across a package called ldapauth-fork. This package seems to be working correctly.

Please check the following link https://www.npmjs.com/package/ldapauth-fork

0

Don't use admin username or password in DN. If you want to authenticate a user, all you need is the user's own username and password.

The dn is the Bind DN in LDAP. Depends on your ldap server configuration, it varies. Use ldapsearch to experiment to find out which one should you use.

I wrote an npm module based on passport-ldapauth to simplify the ldap authentication login.Please check it out at: https://github.com/shaozi/express-passport-ldap-mongoose

Simple usage:

LdapAuth.init(CONFIG.ldap.dn, CONFIG.ldap.url, app,
  (id) => User.findOne({ uid: id }).exec(),
  (user) => User.findOneAndUpdate({ uid: user.uid }, user, { upsert: true, new: true }).exec()
)
Jingshao Chen
  • 3,405
  • 2
  • 26
  • 34
0

A Change in ldapauth-fork/lib/ldapauth.js bindProperty from dn to upn : this.opts.bindProperty || (this.opts.bindProperty = 'userPrincipalName') causes username authentication. Full dn is not needed.

0

After wasting lot of time, I finally able to fix it. Some my findings

  1. {{username}} replacement happens ONLY ON searchFilter. I was doing it on searchBase
  2. Make sure your request body has username and password filed and you have used correct body-parser otherwise passport will notable to extract
  3. As passport was not showing any error it was failing silently, add debugger in two places in the of the library In ldapauth.js search for LdapAuth.prototype.authenticate here you will able to see ldapauth is able to extract password/username

    In strategy.js search for ldap.authenticate here you will be able to see what is the actuall error

Pranoy Sarkar
  • 1,965
  • 14
  • 31