Skip to main content
Announcements
See what Drew Clarke has to say about the Qlik Talend Cloud launch! READ THE BLOG
cancel
Showing results for 
Search instead for 
Did you mean: 
FernandoOliveiraAE
Contributor
Contributor

JWT authentication in mashup error 401 AUTH-1

Could anyone help me identify what might be wrong with this code, as it's returning error 401 AUTH-1

const fs = require("fs");
const uid = require("uid-safe");
const jwt = require("jsonwebtoken");

const payload = {
  jti: uid.sync(32), // 32 bytes random string
  sub: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  subType: "user",
  name: "XXXXXX",
  email: "XXXXXXXXXXXXXXXXXXXXXX",
  email_verified: true,
  groups: ["Administrators", "Sales", "Marketing"],
};

const privateKeyPath = "./privatekey.pem";
const privateKey = fs.readFileSync(privateKeyPath, "utf8");

const headerOptions = {
  algorithm: "HS256",
  keyid: "XXXXXXXXXX",
};

const signOptions = {
  issuer: "XXXXXXXXX.us.qlikcloud.com",
  expiresIn: "5m",
  notBefore: "1s",
  audience: "qlik.api/login/jwt-session",
};

function generateToken() {
  const myToken = jwt.sign(payload, privateKey, {
    ...headerOptions,
    ...signOptions,
  });
  return myToken;
}

let token = generateToken();

var config = {
  host: "XXXXXXXX.us.qlikcloud.com",
  prefix: "/",
  port: 443,
  isSecure: true,
  webIntegrationId: "XXXXXXXXXXXXXXXXXXXXXXXXX",
};

async function login() {
  const response = await fetch(
    `https://${config.host}/login/jwt-session?qlik-web-integration-id=${config.webIntegrationId}`,
    {
      method: "POST",
      credentials: "include",
      mode: "cors",
      headers: {
        "content-type": "application/json",
        Authorization: `Bearer ${token}`,
        "qlik-web-integration-id": config.webIntegrationId
      },
      rejectunAuthorized: false
    }
  );

  console.log(await response.text());

  if ((response.status) !== 200) {
    console.log(await response.text());
    throw new Error("Failed to login via JWT");
  }
}

async function initialize() {
  try {
      await login();
      configureQlik();
  } catch (error) {
      console.error("Error during initialization:", error.message);
  }
}

function configureQlik() {
  require.config({
      baseUrl: `${config.isSecure ? "https://" : "http://"}${config.host}${config.port ? ":" + config.port : ""}${config.prefix}resources`,
      webIntegrationId: config.webIntegrationId
  });

  require(["js/qlik"], function (qlik) {
      qlik.on("error", function (error) {
          $('#popupText').append(error.message + "<br>");
          $('#popup').fadeIn(1000);
      });
      $("#closePopup").click(function () {
          $('#popup').hide();
      });

      var app = qlik.openApp('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', config);
      app.visualization.get('XXXXXXXX').then(function (vis) {
          vis.show("QV01");
      });
  });
}

(async function() {
  try {
    await initialize();
  } catch (error) {
    console.error("Initialization failed:", error);
  }
})();
Labels (2)
2 Replies
Levi_Turner
Employee
Employee

I'd recommend consulting this doc (https://qlik.dev/authenticate/jwt/implement-jwt-authorization/), in a quick scan through (by someone not particularly talented at JavaScript), you're using HS256 whereas we want RS256. Given that we do public / private validation, you can't swap the algos. I would work through known good then adapt to your use case.

FernandoOliveiraAE
Contributor
Contributor
Author

Thanks, but I had already made the change and still couldn't get it to work as expected.
I saw that I need to do it object by object and not as I would like, which would be to take the entire app