Lorem ipsum proin gravida nibh vel velit auctor aliquetenean idelit sollicitudin, lorem quis bibendum auci elit consequat ipsutis sem.
1-677-124-44227

info@yourbusiness.com

184 Main Collins Street | West victoria 8007

Lorem ipsum proin gravida nibh vel velit auctor alique tenean sollicitudin, lorem quis.
Top
JWT-with-NodeJS

Role Based API Access using OpenLDAP and JWT with NodeJS

This blog will give you the idea of Lightweight Directory Access Protocol and JSON Web Token with some practical stuff. But first refresh our concepts about LDAP and JWT. Have a happy reading.

Lightweight Directory Access Protocol (LDAP)

  • LDAP (Lightweight Directory Access Protocol) is a software protocol for enabling anyone to locate organizations, individuals, and other resources such as files and devices in a network, whether on the public Internet or on a corporate intranet.

An LDAP directory is organized in a simple “tree” hierarchy consisting of the following levels:

  1. The root directory (the starting place or the source of the tree), which branches out to
  2. Countries, each of which branches out to
  3. Organizations, which branch out to
  4. Organizational units (divisions, departments, and so forth), which branches out to (includes an entry for)
  5. Individuals (which includes people, files, and shared resources such as printers)
  • Default Port: 389
  • Operation on LDAP:
  1. Search — Performs a search operation against the LDAP server. Responses from the search method are an Event Emitter where you will get a notification for each search Entry that comes back from the server. You will additionally be able to listen for a search Reference, error and end event.
  2. Add — This is used to insert a new entry into the directory-to-server database. If the name entered by a user already exists, the server fails to add a duplicate entry and instead show an “entryAlreadyExists” message.
  3. Bind — On connection with the LDAP server,the default authentication state of the session is anonymous.
  4. Delete — As the name suggests,this operation is used to delete an entry from the directory.In order to do this, the LDAP client has to transmit a perfectly composed delete request to server.
  5. Modify — This operation is used by LDAP clients to make a request for making changes to the already existing database. The change to be made must be one of the following operations:
  6. Add(Including a new value)
  7. Delete(Deleting an already existing value)
  8. Replace(Overwriting an existing value with a new one)
  9. Unbind — This is inverse of the bind operation. Unbind aborts any existing operations and terminates the connection, leaving no response in the end.

Attributes:

  • Distinguished Name:(Mandatory) Known as dn.
  • Object classes: It indicates the type of attributes,schemas associated with the object class.(Example: person, top, posixGroup, posixAccount, uidObject etc.)
  • Attribute Types: It defines the list of attributes that have been used to customize the schema. (Example: gidNumber, uidNumber, cn, givenName, sn )

JSON WEB TOKEN (JWT)

Traditional authentication strategy makes use of session and cookie, but scaling these solutions is very difficult as some kind of state is maintained by the server.JWT, on the other hand, provide a stateless solution for authentication and stateless applications are pretty easy to scale.

JWT is used for authentication and they can also be used for sharing information, most of jwt are signed using a public key and a private key, therefore, it is very difficult to tamper with these token. Jwt has three parts: head, body and signature, each separated by “dot(.)”.

Verification

When the server verifies the token, it creates the hash using the private key if the hash matches the signature on the token then the token is authentic. If the token is tempered with the hash of the token should change but the hacker cannot create the new hash because the key is save with the server. Therefore the token is verified and the client can also be verified using the data in the body.

token=base64url(head)+"."+baser64url(body)+"."+signature

How authentication with JWT works?

The token with username and role is given to the client and the client sends the token back to the server every time the client makes an HTTP request to the server.

body={
 username:"l1s15bscs0105",
 role: "group the user_id belongs to"
}

The client must store the token in the browser. The token can be saved in local storage or session storage. The token is sent to the server in authorization header as Bearer {token} .

Using JWT and OpenLDAP with Nodejs.

If you don’t want to write your own custom jwt solution you can always use an NPM module for it. We would first install express and JSON web token library. Here I am assuming that you have OpenLDAP server configured and up running on Default Port: 389.

npm i express jsonwebtoken express-jwt ldapjs

The directory structure of the project

root
   -index.js
   -config.js
   -authentication
         - auth.js

The config.js contains the private key but it is not a good practice. you should always use env variable for such sensitive data.

const config = {secret : "YUYFDISYFSIERTEWRTEWTWETRNNNMNJHKHFASDdyfiudayDAYIUSDFYASIOFOOASIUDFYEREAHLSKJFE57894502354354HJKAFDDFS"}
module.exports = config;

Let us create a simple express server.

The route /login which takes username and password as the body parameters, first binds the admin to LDAP server and then searches the user’s group by the filter of username and attribute of gidNumber and finally binds the username and password and if successful then issues a token to the user with username and role added as a part of token. Below is the implementation for the this route.

const express = require('express');
const router = express.Router();
const auth = require('./authentication/auth');
var ldap = require('ldapjs')
const jwt = require('jsonwebtoken');
const {secret} = require("./config");var client = ldap.createClient({
url: `ldap://ldap-service:389`,
connectTimeout: 30000,
reconnect: true
});router.post('/login', function(req, res){
   var LDAP_BASE_DN = 'dc=scytalelabs, dc=com';
   var bdn_pass = 'adminPassword';
   var username = req.body.username;
   var password = req.body.password;
var opts = {
   filter: `(uid=${username})`,
   scope: 'sub',
   attributes: ['gidNumber', 'uidNumber' ,'cn','givenName','sn']};try {
     client.bind(  'cn=admin, ' + LDAP_BASE_DN, bdn_pass, function(error) {
  if(error){res.status(500).send('Internal Server Error.');}
  else {
    client.search(LDAP_BASE_DN , opts, function(error, search) {
    var searchList = [];
    search.on('searchEntry', function(entry) {
     searchList.push(entry.object);
     });    search.on('error', function(error) {
     res.status(500).send('Internal Server Error.');
    });    search.on("end", (retVal) => {
     if (searchList.length === 1) {
      // Get a list of groups, try to bind after you get it
      var groupList = [];
      
      client.search(LDAP_BASE_DN,{filter:'((objectclass=posixGroup)(gidNumber=' +   
        searchList[0].gidNumber + '))',
        scope:"sub", attributes:['cn']},      
    (error, searchRes) => {    searchRes.on("searchEntry", (entry) => {
    groupList.push(entry.object);
     });     searchRes.on("error", (error) => {
     res.status(500).send('Internal Server Error.');
     });searchRes.on("end", (entry) => {
     if(groupList.length === 1){
      client.bind(  'cn=' + username +
      ',ou=users,dc=scytalelabs,dc=com', password, function 
        (error) {
          if(error){
          res.status(500).send('Internal Server Error.');
         }
         else {
          const token = jwt.sign({ sub: username, role:   
          groupList[0].cn }, secret, {expiresIn: '1h'});    client.unbind(function(error) {
     if(error){
      res.status(500).send('Internal Server Error.');
      }
     else{
     res.status(200).send(token);
     }
});
}
});
}
else{
res.status(404).send('Group Not Found...');
}
});
});
}
else {
res.status(404).send('User Not Found...');
}
});
});
}
});
} 
catch(error){
client.unbind(function(error) {if(error){console.log(error  );} else{console.log('client disconnected');}});
}
});

The token is sent by the user to the server every time in the request header and the token is authenticated by the auth.isLoggedIn(['role']) middleware every time. The middleware also adds user details to the req as req.user . This middleware should be added to every route that needs to be protected with the allowed roles for the route. Below is the implementation for this middleware.

const expressJwt = require('express-jwt');
const {secret} = require("../config");
exports.isLoggedIn = function (roles = []) {// roles param can be a single role string (e.g. Role.User or
//'User')// or an array of roles (e.g. [Role.Admin, Role.User] or ['Admin', //'User'])if (typeof roles === 'string') {
    roles = [roles];
}return [
// authenticate JWT token and attach user to request object //(req.user)
    
       expressJwt({ secret }),
// authorize based on user role
      (req, res, next) => {
       if (roles.length && !roles.includes(req.user.role)) {
         // user's role is not authorized
  return res.status(401).json({ message: 'Unauthorized Access' });
}// authentication and authorization successful
next();
}];
}

I hope that you got the basic understanding of how to make your API secure with LDAP and JWT based on roles. If any confusions, please feel free to ask in the response section.

16 Comments
  • ExoRank.com

    January 28, 2020 at 12:03 pm

    Awesome post! Keep up the great work! 🙂

  • AffiliateLabz

    February 16, 2020 at 3:35 am

    Great content! Super high-quality! Keep it up! 🙂

  • best cbd oil

    May 4, 2020 at 9:23 am

    My partner and I absolutely love your blog and find a lot of
    your post’s to be exactly I’m looking for. Do you offer guest writers to write content for you
    personally? I wouldn’t mind creating a post or elaborating on a
    number of the subjects you write related to here. Again, awesome weblog!

  • best cbd oil

    May 4, 2020 at 8:27 pm

    What’s up, after reading this remarkable piece of writing
    i am as well happy to share my experience here with friends.

    • zaid Munir

      May 14, 2020 at 9:02 pm

      Hello CBD oil
      We are glad you find our blog helpful. If you feel you would like to contribute we can work out some mechanism. We haven’t yet allowed guest content writers. We can discuss what sort of content you wish to share?

  • http://cumshot.icu/

    May 21, 2020 at 2:13 am

    Its such as you read my thoughts! You seem to know a lot approximately this, such as you
    wrote the ebook in it or something. I think that you could do with a few percent to pressure the message home a
    bit, but instead of that, this is great blog. A fantastic
    read. I’ll definitely be back.

  • Maritza Bohac

    June 1, 2020 at 10:24 am

    Awesome write-up. I am a regular visitor of your blog and appreciate you taking the time to maintain the excellent site. I will be a regular visitor for a really long time.

  • Latoya Saelee

    June 3, 2020 at 8:31 am

    I must spend some time studying much more or understanding more.

  • Lottie

    June 13, 2020 at 12:44 pm

    What’s Going down i’m new to this, I stumbled upon this I have found It absolutely useful and
    it has aided me out loads. I hope to contribute
    & assist different customers like its helped me. Good job.

  • Alisha

    June 25, 2020 at 7:51 am

    Saved as a favorite, I really like your web site!

  • Tremblay

    July 1, 2020 at 1:27 pm

    I am truly grateful to the holder of this web site who has
    shared this great post at here.

  • Marina

    July 4, 2020 at 4:57 am

    Hi there! This is my 1st comment here so I just wanted
    to give a quick shout out and tell you I truly
    enjoy reading your articles. Can you suggest any other blogs/websites/forums that cover the same subjects?

    Thank you!

  • Skincell free trial

    July 5, 2020 at 6:02 am

    I blog frequently and I truly thank you for
    your content. This great article has truly peaked my interest.
    I will bookmark your blog and keep checking for new information about once a week.
    I subscribed to your Feed as well.

  • Hannah

    July 5, 2020 at 6:19 am

    Keep on working, great job!

  • Kennedi

    July 6, 2020 at 5:25 am

    Hello, yup this paragraph is genuinely pleasant and I have learned lot of things from it regarding blogging.
    thanks.

  • Selina Arvin

    July 14, 2020 at 12:11 pm

    I believe you have mentioned some very interesting points, regards for the post. 🙂

Add Comment
Name*
Email*
Website

Website Protected by Spam Master