The Next Level3 Node.js integration is designed to be used for your existing applications or sites that are using native Node.js code for authentication. This integration will allow you to easily add Account Protection to any application the leverages Node.js for authentication. 

pre-requisites

 

Requirements: 

– Node.js Application
– Next Level3 Company Account
– Signing Key created for an application in the Next Level3 Company Portal

 

Account Protection

The following Node.js code sample can be used to integrate an account protection check into your existing authentication flow for  custom Node.js applications that are handling authentication within the application or where a third-party identity provider does not have a supported integration:

				
					const https = require("https");
const nJwt = require("njwt");

function getLockStatus(jwt, apiHost, apiPath, requestHeaders) {
  return new Promise((resolve, reject) => {
    const postData = JSON.stringify({
      userIP: requestHeaders["x-forwarded-for"],
      userDevice: requestHeaders["user-agent"],
      userLocation: "",
      integrationType: "aadb2c",
      integrationData: {},
    });
    const options = {
      host: apiHost,
      port: "443",
      path: apiPath,
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
        "x-nl3-authorization-token": jwt,
        "Content-Length": Buffer.byteLength(postData),
      },
    };

    const req = https.request(options, (response) => {
      const chunksOfData = [];

      response.on("data", (fragments) => {
        chunksOfData.push(fragments);
      });

      response.on("end", () => {
        const responseBody = Buffer.concat(chunksOfData);
        resolve(responseBody.toString());
      });
      response.on("error", (error) => {
        console.log(`Error = ${error.message}`);
        reject(error);
      });
    });
    req.write(postData);
    req.end();
  });
}

module.exports = async function (context, req) {
  let responseMessage = "";
  let responseStatus = 200;
  const claims = {
    iss: process.env.APP_URI,
    aud: process.env.API_HOST,
    sub: req.body.signInName, // UserId for which to check lock status
  };
  /* Signing Key would ideally be stored and retrieved from a secrets manager
     and not an environmental variable */
  const decodedDomainToken = Buffer.from(process.env.SIGNING_KEY, "base64");
  const jwt = nJwt.create(claims, decodedDomainToken);
  jwt.setExpiration(new Date().getTime() + 60 * 5 * 1000); // 5 minute expiration
  jwt.setNotBefore(new Date().getTime() - 60 * 1 * 1000); // 1 minute leeway
  const authToken = jwt.compact();

  const res = await getLockStatus(
    authToken,
    process.env.API_HOST,
    process.env.API_PATH,
    req.headers
  );
  const result = JSON.parse(res);
  let failed = false;

  if (result) {
    context.log(JSON.stringify(result));
    if (Object.prototype.hasOwnProperty.call(result, "locked")) {
      if (result.locked) {
        // Code to deny login
      }
    } else {
      failed = true;
    }
  } else {
    failed = true;
  }
  if (failed) {
    if (process.env.FAIL_CLOSED == "true") {
      // Code to deny login
    }
  } else {
    // Code to allow login
  }
};
				
			

Scroll to Top