使用passport-ldapauth的LDAP身份验证



我正在尝试使用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消息缺少用户名/密码(默认:' missing credentials')

下面是我的配置:

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

"OPTS"中的"usernameField"one_answers"passwordField"可选。我的程序使用默认值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'
})); 

根据passport-ldapauth提供的文档,作为server值的对象不包含usernameFieldpasswordField。你的策略应该是这样的:

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

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

请检查以下必须执行用户基本身份验证的代码。此代码在必须验证用户登录凭据时起作用。

我们需要使用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等字段没有用处。免责声明是,你需要测试它是否为真

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

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

请使用"LDAP Authentication"检查NPM

您将遇到一个名为ldapauth-fork的包。

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

不要在DN中使用admin用户名或密码。如果你想验证一个用户,你所需要的只是用户自己的用户名和密码。

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

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

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

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

    strategy.js中搜索ldap.authenticate,你可以看到实际错误是什么

最新更新