Native Language Integrations

Next Level3 supports protecting your applications by integrating Cloud Identity JIT Access directly to your application. To integrate Next Level3 authentication into your application, refer to the corresponding native language instructions below.

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 that leverages Node.js.

Pre-requisites

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

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
          }
        };