<commit_before>'use strict';
const _ = require('lodash'),
  expressJwt = require('express-jwt'),
  jwt = require('jsonwebtoken'),
  unless = require('express-unless'),
  util = require('util'),
  jwksClient = require('jwks-rsa');

const BASE64_REGEX = /^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2}==|[A-Za-z0-9-_]{3}=)?$/;

// private function for computing the routes we do not need to apply auth0 to
const getExcludedRoutes = function (configuredExclusions) {
  // there's a few routes we know should be free of authentication
  const defaultExcludedRoutes = ['/livecheck', '/swagger', '/authtools/widget.js', '/authtools/connections.js'],
    routesToExclude = _.union(defaultExcludedRoutes, configuredExclusions || []);

  // Exclude all sub-routes of the configured excluded routes
  var excludedRoutesRegex = _.map(routesToExclude, function (route) {
    if (_.isString(route)) {
      return new RegExp(route, 'i');
    } else if (route.url) { // support the url/method key-pair
      if (!(route.url instanceof RegExp)) {
        route.url = new RegExp(route.url, 'i');
      }
      return route;
    } else {
      return route;
    }
  });

  //only match the root
  excludedRoutesRegex.push(new RegExp('^/$', 'ig'));

  return excludedRoutesRegex;
};

const getAuthPublicKey = function (jwksUrl, cache, kid) {
  cache.get(`kid${kid}`).then(function (data) {
    if (!data) {
      var client = jwksClient({
        cache: true,
        cacheMaxEntries: 5,
        cacheMaxAge: ms('10h'),
        JwksUri
      });
      client.getSigningKey(kid, (err, key) => {
        if (err) {
          return null;
        } else {
          var signingKey = key.publicKey || key.rsaPublicKey;
          var encodedValue = new Buffer(signingKey).toString("base64");
          cache.set(`kid${kid}`, encodedValue, 36000).then(() => {
            return new Buffer(signingKey);
          });
        }
      });
    } else {
      return new Buffer(data, "base64");
    }
  });
};

// secures the application with auth0, by implementing checks against
// incoming jwt's, with configuration of what routes to apply it to
module.exports = function (app, config, logger, cache) {

  // make sure we are configured to use auth0, otherwise, we dont need to
  // actually apply anything
  const auth0AppConfig = _.get(config, 'app.auth0.application');
  const auth0Domain = _.get(config, 'app.auth0.domain');
  const jwksUrl = _.get(config, 'app.auth0.jwksUrl');

  if (auth0AppConfig) {
    // decode the client secret if it is base64 encoded
    var secret;
    if (auth0AppConfig.secret.match(BASE64_REGEX)) {
      secret = new Buffer(auth0AppConfig.secret, 'base64');
    } else {
      secret = auth0AppConfig.secret;
    }

    // set up jwt validation, which will take into account excluded routes
    var v1JwtCheck = expressJwt({
      secret: secret,
      audience: auth0AppConfig.clientId
    });

    if (auth0AppConfig.resourceServer && jwksUrl) {
      const v2JwtCheck = expressJwt({
        // Look up the public key to use based on the KID (key id) contained in the
        // header of the JWT.
        secret: (req, header, _payload, done) => {
          if (!header || !header.kid) {
            return done(new Error("JWT KID Not Found"));
          }
          var publicKey = getAuthPublicKey(jwksUrl, cache, header.kid);
          if (publicKey) {
            return done(null, publicKey);
          } else {
            return done(new Error("Public Key not found for KID " + header.kid));
          }
        },
        audience: auth0AppConfig.resourceServer,
        issuer: 'https://' + auth0Domain + '/',
        algorithms: ['RS256']
      });
    }

    let jwtAuthentication = function authentication(req, res, next) {
      // Use the v2 JWT middleware if:
      // 1) an `auth0.application.resourceServer` has been specified via the config object<commit_msg>fix(authv2): Authv2 check needed to go up a level<commit_after>'use strict';
const _ = require('lodash'),
  expressJwt = require('express-jwt'),
  jwt = require('jsonwebtoken'),
  unless = require('express-unless'),
  util = require('util'),
  jwksClient = require('jwks-rsa');

const BASE64_REGEX = /^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2}==|[A-Za-z0-9-_]{3}=)?$/;

// private function for computing the routes we do not need to apply auth0 to
const getExcludedRoutes = function (configuredExclusions) {
  // there's a few routes we know should be free of authentication
  const defaultExcludedRoutes = ['/livecheck', '/swagger', '/authtools/widget.js', '/authtools/connections.js'],
    routesToExclude = _.union(defaultExcludedRoutes, configuredExclusions || []);

  // Exclude all sub-routes of the configured excluded routes
  var excludedRoutesRegex = _.map(routesToExclude, function (route) {
    if (_.isString(route)) {
      return new RegExp(route, 'i');
    } else if (route.url) { // support the url/method key-pair
      if (!(route.url instanceof RegExp)) {
        route.url = new RegExp(route.url, 'i');
      }
      return route;
    } else {
      return route;
    }
  });

  //only match the root
  excludedRoutesRegex.push(new RegExp('^/$', 'ig'));

  return excludedRoutesRegex;
};

const getAuthPublicKey = function (jwksUrl, cache, kid) {
  cache.get(`kid${kid}`).then(function (data) {
    if (!data) {
      var client = jwksClient({
        cache: true,
        cacheMaxEntries: 5,
        cacheMaxAge: ms('10h'),
        JwksUri
      });
      client.getSigningKey(kid, (err, key) => {
        if (err) {
          return null;
        } else {
          var signingKey = key.publicKey || key.rsaPublicKey;
          var encodedValue = new Buffer(signingKey).toString("base64");
          cache.set(`kid${kid}`, encodedValue, 36000).then(() => {
            return new Buffer(signingKey);
          });
        }
      });
    } else {
      return new Buffer(data, "base64");
    }
  });
};

// secures the application with auth0, by implementing checks against
// incoming jwt's, with configuration of what routes to apply it to
module.exports = function (app, config, logger, cache) {

  // make sure we are configured to use auth0, otherwise, we dont need to
  // actually apply anything
  const auth0AppConfig = _.get(config, 'app.auth0.application');
  const auth0Domain = _.get(config, 'app.auth0.domain');
  const jwksUrl = _.get(config, 'app.auth0.jwksUrl');

  if (auth0AppConfig) {
    // decode the client secret if it is base64 encoded
    var secret;
    if (auth0AppConfig.secret.match(BASE64_REGEX)) {
      secret = new Buffer(auth0AppConfig.secret, 'base64');
    } else {
      secret = auth0AppConfig.secret;
    }

    // set up jwt validation, which will take into account excluded routes
    var v1JwtCheck = expressJwt({
      secret: secret,
      audience: auth0AppConfig.clientId
    });

    let v2JwtCheck;
    if (auth0AppConfig.resourceServer && jwksUrl) {
      v2JwtCheck = expressJwt({
        // Look up the public key to use based on the KID (key id) contained in the
        // header of the JWT.
        secret: (req, header, _payload, done) => {
          if (!header || !header.kid) {
            return done(new Error("JWT KID Not Found"));
          }
          var publicKey = getAuthPublicKey(jwksUrl, cache, header.kid);
          if (publicKey) {
            return done(null, publicKey);
          } else {
            return done(new Error("Public Key not found for KID " + header.kid));
          }
        },
        audience: auth0AppConfig.resourceServer,
        issuer: 'https://' + auth0Domain + '/',
        algorithms: ['RS256']
      });
    }

    let jwtAuthentication = function authentication(req, res, next) {
      // Use the v2 JWT middleware if:
      // 1) an `auth0.application.resourceServer` has been specified via the config object
{'fraction_non_alphanumeric': 0.13248081841432224, 'fraction_numerical': 0.013938618925831201, 'mean_word_length': 2.696124763705104, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3794272', 'n_tokens_mistral': 2480, 'n_tokens_neox': 2409, 'n_words': 674}