使用passport-ldapauth npm进行LDAP身份验证

时间:2015-06-08 10:49:05

标签: node.js ldap passport.js openldap

我正在尝试使用passport-ldapauth npm验证openLDAP用户名和密码。执行以下代码时,我总是收到错误 { message: 'Missing credentials' }。请帮助我解决我的代码有什么问题。

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

有关详细信息,请参阅此badRequestMessage flash message for missing username/password (default: 'Missing credentials')

9 个答案:

答案 0 :(得分:7)

这是我的配置:

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);
});

usernameField中的passwordFieldOPTS是可选的。我的程序使用默认值usernamepassword。如果设置了usernameField,则需要将searchFilter修改为(sAMAccountName={{<usernameField value>}})(uid={{<usernameField value>}})

此外,为了在会话中存储登录状态,需要express-session模块。会话配置如下:

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

然后,您可以将LDAP身份验证用作:

app.post('/login', passport.authenticate('ldapauth', {
  successRedirect: '/users/profile', failureRedirect: '/login'
})); 

答案 1 :(得分:1)

根据passport-ldapauth提供的文档,服务器的值对象不包含 usernameField passwordField 。您的策略应该如下:

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

但正如G Chen在回答中提到的那样,usernameField和passwordField是可选的。

答案 2 :(得分:1)

请检查以下代码,其中必须执行用户的基本身份验证。必须验证用户登录凭据时,此代码才有效。

我们需要使用3个字段即。 usernameField,passwordField和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
};

像Userbooster light这样的LDAP管理工具对于理解身份验证过程的发生方式非常有用。

searchBase,searchFilter等字段没用。然而,免责声明是您需要测试是否真实

答案 3 :(得分: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 ");
   }
});

答案 4 :(得分:0)

可能问题不是由passport-ldapauth引起的。您的帖子请求可能存在一些问题。在使用[usernameField]之前,请检查您的请求中是否有[passwordField]passport.authenticate

答案 5 :(得分:0)

请使用“LDAP身份验证”

检查NPM

您会遇到一个名为ldapauth-fork的软件包。这个包似乎工作正常。

请检查以下链接https://www.npmjs.com/package/ldapauth-fork

答案 6 :(得分:0)

请勿在DN中使用管理员用户名或密码。如果您想对用户进行身份验证,您只需要用户自己的用户名和密码。

dn是LDAP中的绑定DN。取决于您的ldap服务器配置,它会有所不同。使用ldapsearch进行试验,找出您应该使用哪一个。

我写了一个基于passport-ldapauth的npm模块来简化ldap身份验证登录。请查看:https://github.com/shaozi/express-passport-ldap-mongoose

简单用法:

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

答案 7 :(得分:0)

将ldapauth-fork / lib / ldapauth.js bindProperty从dn更改为upn: this.opts.bindProperty || (this.opts.bindProperty = 'userPrincipalName') 导致用户名认证。 不需要完整的dn。

答案 8 :(得分:0)

浪费大量时间后,我终于能够修复它。我的一些发现

  1. {{username}}替换发生在ONLY ON searchFilter。我是在searchBase
  2. 上进行的
  3. 确保您的请求正文已提交usernamepassword,并且您使用了正确的body-parser,否则护照将无法提取
  4. 由于护照没有显示任何错误,因此它无声地失败,请在库的两个位置添加调试器 在ldapauth.js中搜索LdapAuth.prototype.authenticate,您将看到ldapauth能够提取密码/用户名

    strategy.js中搜索ldap.authenticate,您将看到什么是实际错误