0.1.1 • Published 10 years ago

node-ldapauthz v0.1.1

Weekly downloads
5
License
-
Repository
-
Last release
10 years ago

node-ldapauthz

A simple node.js lib for user authorization based on LDAP server groups.

License

##Installation

$ npm install connect-roles

Usage

 var LdapAuthz = require('ldapauthz');
 
 var authz = new LdapAuthz({url: 'ldaps://ldap.example.com:663', ...});
 
 ...
 
 authz.getGrantedAuthorities(username, function (err, authorities) { ... });
 
 ...
 
 authz.close(function (err) { ... }) 

API

LdapAuthz(opts)

Creates an LDAP authz class.

  • opts {Object} Configuration options
    • url {String} A valid LDAP url. E.g. 'ldaps://ldap.example.com:663'
    • adminDn {String} Optional, e.g. 'uid=myapp,ou=users,o=example.com'
    • adminPassword {String} Password for adminDn.
    • groupSearchBase {String} Defines the part of the directory tree under which group searches should be performed. E.g. 'ou=groups,o=example.com'
    • groupSearchScope {String} Optional, default 'sub'. Scope of the search, one of 'base', 'one', or 'sub'.
    • groupSearchFilter {String} The filter which is used to search for group membership. Use the literal '{{username}}' to have the given username be interpolated in for the LDAP search. The default is (uniqueMember={{username}}), corresponding to the groupOfUniqueMembers LDAP class.
    • groupRoleAttribute {String} The attribute which contains the name of the authority defined by the group entry. Defaults to cn.
    • log4js Optional. The require'd log4js module to use for logging. If given this will result in TRACE-level logging for ldapauthz.
    • verbose {Boolean} Optional, default false. If log4js is also given, this will add TRACE-level logging for ldapjs (quite verbose).
    • timeout {Integer} Optional, default Infinity. How long the client should let operations live for before timing out.
    • connectTimeout {Integer} Optional, default is up to the OS. How long the client should wait before timing out on TCP connections.
    • tlsOptions {Object} Additional options passed to the TLS connection layer when connecting via ldaps://. See http://nodejs.org/api/tls.html#tls_tls_connect_options_callback for available options.
    • maxConnections {Integer} Whether or not to enable connection pooling, and if so, how many to maintain.
    • bindDN {String} The DN all connections should be bound as. Defaults to adminDn.
    • bindCredentials {String} The credentials to use with bindDN. Defaults to adminPassword.
    • checkInterval {Integer} How often to schedule health checks for the connection pool.
    • maxIdleTime {Integer} How long a client can be idle before health-checking the connection (subject to the checkInterval frequency).

close(callback)

Closes the LDAP client.

  • callback {Function} Callback function.

getGrantedAuthorities(username, callback);

Gets the list of authorities for the user.

  • username {String} The user name.
  • callback {Function} function (err, authorities) The callback function.

Examples

Example using express, passport and connect-roles

const URL = 'ldap://localhost:389';
const ADMIN_DN = 'cn=root,ou=person,dc=sample,dc=com';
const ADMIN_PASSWORD = 'secret';

const SEARCH_BASE = 'ou=person,dc=sample,dc=com';
const SEARCH_FILTER = '(&(objectclass=inetOrgPerson)(uid={{username}}))';

const GROUP_SEARCH_BASE = 'ou=group,dc=sample,dc=com';
const GROUP_SEARCH_FILTER = '(&(uniqueMember={{username}})(objectClass=group))';

var _ = require("underscore"),
  express = require('express'),
  bodyParser = require('body-parser'),
  session = require('express-session'),
  cookieParser = require('cookie-parser'),
  passport = require('passport'),
  LdapStrategy = require('passport-ldapauth').Strategy,
  ConnectRoles = require('connect-roles'),
  LdapAuthz = require('./ldapauthz.js');

var app = express();

var user = new ConnectRoles();

passport.use(new LdapStrategy({
    server: {
      url: URL,
      adminDn: ADMIN_DN,
      adminPassword: ADMIN_PASSWORD,
      searchBase: SEARCH_BASE,
      searchFilter: SEARCH_FILTER
    }
  },
  function(user, done) {

    console.log('user: ' + user.dn);

    var authz = new LdapAuthz({
      url: URL,
      adminDn: ADMIN_DN,
      adminPassword: ADMIN_PASSWORD,
      groupSearchBase: GROUP_SEARCH_BASE,
      groupSearchFilter: GROUP_SEARCH_FILTER
    });

    authz.getGrantedAuthorities(user.dn, function (err, authorities) {
      authz.close(function (err) {});

      if (err) {
        return done(err);
      }

      user.roles = authorities;
      return done(null, user);
    });
  }
));

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

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

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(session({ secret: 'keyboard cat', saveUninitialized: true, resave: true }));
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
app.use(user.middleware());

// Anonymous users can only access the home page
// Returning false stops any more rules from being considered
user.use(function (req, action) {
  if (!req.isAuthenticated()) {
    return action === 'access home page';
  }
})

user.use('user', function (req) {
  return  _.contains(req.user.roles, 'GEC-BR-search-usuarios');
});

user.use('admin', function (req) {
  return  _.contains(req.user.roles, 'GEC-BR-search-administradores');
});

app.get('/', user.can('access home page'), function (req, res) {
  res.send({status: 'home - ok'}).end();
});

app.get('/login', passport.authenticate('ldapauth'), function(req, res) {
  res.send({status: 'login - ok'}).end();
});

app.get('/user', user.is('user'), function (req, res) {
  res.send({status: 'user - ok'}).end();
});

app.get('/admin', user.is('admin'), function (req, res) {
  res.send({status: 'admin - ok'}).end();
});

app.listen(8080);