LDAP Authentication with NodeJS, Express, and Passport-ldapauth
Asked Answered
P

4

8

I"m having trouble authenticating to an Active Directory Server with the tools/applications mentioned in the title.

I'm using a test AD environment found here Here are the relevant code snippets, if anyone has any suggestions I would really appreciate it.

Currently, the error i'm getting is "invalid username/password". I'm not sure if this is the bindDn account/pw or the one the user enters in the form. According to the passport-ldapauth project it's:

invalidCredentials flash message for InvalidCredentialsError
NoSuchObjectError, and 
/no such user/i LDAP errors (default: 'Invalid     username/password')

Thanks in advance.

CLIENT - auth.service.js

...

login: function(user, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();

$http.post('/auth/ldap', {
  email: user.email,
  password: user.password
}).
success(function(data) {
  $cookieStore.put('token', data.token);
  currentUser = User.get();
  deferred.resolve(data);
  return cb();
}).
error(function(err) {
  this.logout();
  deferred.reject(err);
  return cb(err);
}.bind(this));

return deferred.promise;
},

...

SERVER index.js

'use strict';

var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');

var router = express.Router();

router.post('/', function(req, res, next) {
  passport.authenticate('ldapauth', function (err, user, info) {
    var error = err || info;
    if (error) return res.json(401, error);
    if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});

    var token = auth.signToken(user._id, user.role);
    res.json({token: token});
  })(req, res, next)
});

module.exports = router;

SERVER passport.js

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

exports.setup = function (User, config) {
  passport.use(new LdapStrategy({
      usernameField: 'email',
      passwordField: 'password',
      server: {
        url: 'ldap://ldap.forumsys.com:389',
        bindDn: "cn=read-only-admin,dc=example,dc=com",
        bindCredentials: "password",
        searchBase: 'ou=mathematicians,dc=example,dc=com',
        searchFilter: 'uid={{username}}'
      }
    },
    function (user, done) {  
      return done(null, user);
    }
  ));
};
Pul answered 26/1, 2015 at 21:29 Comment(0)
A
5

The problem is with the ou=mathematicians in the search base. There is the following mention in the comments on that web page:

The issue you are seeing is due to the fact that “uid=riemann” is a member of “ou=mathemeticians”, but does not reside under that ou. His membership in that ou is established by a uniqueMember attribute on “ou=mathemeticians”.

This should work (tried it even with ldapauth-fork which passport-ldapauth uses):

var opts = {
  server: {
    "url": "ldap://ldap.forumsys.com:389",
    "adminDn": "cn=read-only-admin,dc=example,dc=com",
    "adminPassword": "password",
    "searchBase": "dc=example,dc=com",
    "searchFilter": "(uid={{username}})",
  }
};
Alysonalysoun answered 24/2, 2015 at 19:45 Comment(0)
R
2

For whose still lose your way, here is my code snippet in Typescript.

Server Side

import * as express from 'express'
import * as bodyParser from 'body-parser'
import * as cors from 'cors'
import * as passport from 'passport'
import * as ldapstrategy from 'passport-ldapauth'

// connect to LDAP server
const OPTS: ldapstrategy.Options = {
  server: {
    url: "ldap://ldap.forumsys.com",
    bindDN: "cn=read-only-admin,dc=example,dc=com",
    bindCredentials: 'password',
    searchBase: "dc=example,dc=com",
    searchFilter: "(uid={{username}})"
  }
}

passport.use(new ldapstrategy(OPTS))

// instantiate the server
const app = express()
// parse the request data automatically
app.use(bodyParser.json())
// allow cross origin resource sharing
app.use(cors())
// inject LDAP connection to express server
app.use(passport.initialize())

// listen to port defined
const port = process.env.PORT || 8085
app.listen(port, (): void => {
  console.log(`Listening on port ${port}`)
})

app.post('/login', (req: express.Request, res: express.Response, next: express.NextFunction): void | Response => {
  passport.authenticate('ldapauth', (err, user, info): void => {
    var error = err || info
    if (error) 
      res.send({
        status: 500,
        data: error
      })
    if (!user) 
      res.send({
        status: 404,
        data: "User Not Found"
      })
    else
      res.send({
        status: 200,
        data: user
      })
  })(req, res, next)
})

Client Side

Postman Example

Retrogradation answered 28/4, 2019 at 5:52 Comment(0)
T
1

Your code looks correct, but the error you're getting leads me to believe you really don't have the correct username/password supplied! Are you sure you're testing with the right credentials?

As a sidenote -- if you're looking for a simpler way to do this for a big project, and don't mind spending some money, Stormpath's API service does this sort of thing for you: it basically syncs your AD / LDAP users into it's API service so you can work with them via a REST API (it's much simpler).

There are two libraries you can use to work with it:

Both are pretty simple / nice to use.

Therapeutic answered 27/1, 2015 at 23:34 Comment(0)
D
0

this code me phpLDAPadmin express.js and passport-ldapauth

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

const OPTS = {
  server: {
    url: 'ldap://localhost:389',
    bindDN: 'cn=admin,dc=ramhlocal,dc=com',
    bindCredentials: 'password',
    searchBase: 'dc=ramhlocal,dc=com',
    searchFilter: '(uid={{username}})'
  }
};

var app = express();

passport.use(new LdapStrategy(OPTS));

app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(passport.initialize());


app.post('/login', function (req, res, next){
  passport.authenticate('ldapauth', {session: false}, function(err, user, info) {
    var error = err || info
    console.log(user);
    if (error) 
      res.send({
        status: 500,
        data: error
      })
    if (! user) {
      res.send({
        status: 404,
        data: "User Not Found"
      })
    }
    res.send({
      status: 200,
      data: user
    })
  })(req, res,next)
})
app.listen(8080);

enter image description here

Downgrade answered 8/7, 2021 at 8:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.