text: var jwt = require('jsonwebtoken');
  var UnauthorizedError = require('./errors/UnauthorizedError');
  var unless = require('express-unless');
  var async = require('async');
  var set = require('lodash.set');
  const fs = require("fs")
  
  var DEFAULT_REVOKED_FUNCTION = function(_, __, cb) { return cb(null, false); };
  
  function isFunction(object) {
    return Object.prototype.toString.call(object) === '[object Function]';
  }
  
  function wrapStaticSecretInCallback(secret){
    return function(_, __, cb){
      return cb(null, secret);
    };
  }
  
  module.exports = function(options) {
    if (!options || !options.secret) throw new Error('secret should be set');
  
    if (!options.algorithms) throw new Error('algorithms should be set');
    if (!Array.isArray(options.algorithms)) throw new Error('algorithms must be an array');
  
    var secretCallback = options.secret;
  
    if (!isFunction(secretCallback)){
      secretCallback = wrapStaticSecretInCallback(secretCallback);
    }
  
    var isRevokedCallback = options.isRevoked || DEFAULT_REVOKED_FUNCTION;
  
    var _requestProperty = options.userProperty || options.requestProperty || 'user';
    var _resultProperty = options.resultProperty;
    var credentialsRequired = typeof options.credentialsRequired === 'undefined' ? true : options.credentialsRequired;
  
    var middleware = function(req, res, next) {
      var token;
  
      if (req.method === 'OPTIONS' && req.headers.hasOwnProperty('access-control-request-headers')) {
        var hasAuthInAccessControl = !!~req.headers['access-control-request-headers']
                                      .split(',').map(function (header) {
                                        return header.trim();
                                      }).indexOf('authorization');
  
        if (hasAuthInAccessControl) {
          return next();
        }
      }
  
      if (options.getToken && typeof options.getToken === 'function') {
        try {
          token = options.getToken(req);
        } catch (e) {
          return next(e);
        }
      } else if (req.headers && req.headers.authorization) {
        var parts = req.headers.authorization.split(' ');
        if (parts.length == 2) {
          var scheme = parts[0];
          var credentials = parts[1];
  
          if (/^Bearer$/i.test(scheme)) {
            token = credentials;
          } else {
            if (credentialsRequired) {
              return next(new UnauthorizedError('credentials_bad_scheme', { message: 'Format is Authorization: Bearer [token]' }));
            } else {
              return next();
            }
          }
        } else {
          return next(new UnauthorizedError('credentials_bad_format', { message: 'Format is Authorization: Bearer [token]' }));
        }
      }
  
      if (!token) {
        var routes = process.env.API_KEY_ROUTE_ACCESS.split(',')
        let rawdata = fs.readFileSync(process.env.STATIC_API_KEYS);
        let apiKeys = JSON.parse(rawdata);
  
        if(apiKeys.hasOwnProperty(req.headers['x-api-user-id'])){
          if(routes.some(e => req.originalUrl.includes(e)) && apiKeys[req.headers['x-api-user-id']].includes(req.method)){
              return next();
          }
          else{
            return next(new UnauthorizedError('invalid_request',{message:'Unauthorized route access'}))
          }
        }
        if (credentialsRequired) {
          return next(new UnauthorizedError('credentials_required', { message: 'No authorization token was found' }));
        } else {
          return next();
        }
      }
  
      var dtoken;
  
      try {
        dtoken = jwt.decode(token, { complete: true }) || {};
      } catch (err) {
        return next(new UnauthorizedError('invalid_token', err));
      }
  
      async.waterfall([
        function getSecret(callback){
          var arity = secretCallback.length;
          if (arity == 4) {
            secretCallback(req, dtoken.header, dtoken.payload, callback);
          } else { // arity == 3
            secretCallback(req, dtoken.payload, callback);
          }
        },
        function verifyToken(secret, callback) {
          jwt.verify(token, secret, options, function(err, decoded) {
            if (err) {
              callback(new UnauthorizedError('invalid_token', err));
            } else {
              callback(null, decoded);
            }
          });
        },
        function checkRevoked(decoded, callback) {
          isRevokedCallback(req, dtoken.payload, function (err, revoked) {
            if (err) {
              callback(err);
            }
            else if (revoked) {
              callback(new UnauthorizedError('revoked_token', {message: 'The token has been revoked.'}));
            } else {
              callback(null, decoded);
            }
          });
        }
  
      ], function (err, result){
        if (err) { return next(err); }
        if (_resultProperty) {
          set(res, _resultProperty, result);
        } else {
          set(req, _requestProperty, result);
        }
        next();
      });
    };
  
    middleware.unless = unless;
    middleware.UnauthorizedError = UnauthorizedError;
  
    return middleware;
  };
  
  module.exports.UnauthorizedError = UnauthorizedError;
  