LDAP authentication using passport-ldapauth npm
Asked Answered
P

9

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')

Purpure answered 8/6, 2015 at 10:49 Comment(5)
Are the values in your OPTS object actually what appear above, or did you remove them for this post?Arleyne
@Arleyne I have removed the actual values for this postPurpure
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: #28159593. 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.Arleyne
@Arleyne as per the documentation given in npmjs.com/package/passport-ldapauth, I tried the Express example which gives me error "Missing Credentials"Purpure
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!Arleyne
F
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'
})); 
Foresail answered 26/8, 2015 at 16:47 Comment(2)
"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>}})." Could you give an example for this? For instance, if I search for the user "test", should the usernameField be "test"?Plumbing
@Plumbing No, usernameField and passwordField are the login form fields' names. If your login page HTML contains eg. <input name="weirdusernamefield" type="text"/> 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.Parrisch
J
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.

Jog answered 17/2, 2016 at 22:31 Comment(0)
P
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

Pinchas answered 3/8, 2017 at 21:43 Comment(0)
P
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 ");
   }
});
Pinchas answered 6/9, 2017 at 18:33 Comment(1)
i have an issue about this approach #51763957Levitus
H
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.

Headsail answered 20/6, 2017 at 1:54 Comment(0)
P
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

Pinchas answered 10/8, 2017 at 16:33 Comment(0)
G
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()
)
Garget answered 12/3, 2018 at 13:59 Comment(0)
S
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.

Silicious answered 9/9, 2019 at 18:44 Comment(0)
M
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

Microlith answered 2/12, 2019 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.