Build a simple NodeJs OAuth client to access Qlik Sense SaaS

1 Introduction

This tutorial shows you how to use a NodeJs client with Qlik Sense SaaS.

2 Prerequisites

  1. Using the Management Console, create an OAuth client with your callback URL.
  2. Save the client ID and client secret. This is needed for configuration below.

More details are available at

Create an OAuth Client

3 Setup

3.1 Configure NodeJs client

In addition, there are other configurations to set but by using openid-client, you can grab most of the configurations from the Qlik Sense SaaS tenant's discovery endpoint.

const { generators, Issuer } = require('openid-client');
class IdP {
  constructor() {
    this.discovery_url = `${qlikOauthHost}/.well-known/openid-configuration`;
    this.redirect_uris = [`${clientHost}/login/callback`];
    this.scope = 'user_default offline_access'; // offline_access only needed it you want refresh tokens
    this.client_id = 'clientId';
    this.client_secret = 'clientSecret';
    // Not a proper userinfo endpoint as it has additional data
    this.userinfo_endpoint = `${qlikOauthHost}/api/v1/users`;
  }

  async initiate() {
    const issuer = await this.discover();
    // The discovery endpoint is missing userinfo endpoint, so we can add it manually if we want it. Otherwise, the issuer returned from the discover is sufficient.
    this.issuer = this.issueIssuer(issuer);

    this.client = new this.issuer.Client({
      client_id: this.client_id,
      client_secret: this.client_secret,
      redirect_uris: this.redirect_uris,
      response_types: this.issuer.response_types_supported,
      token_endpoint_auth_method: 'client_secret_post',
    });
  }

  issueIssuer(issuer) {
    return new Issuer({
      issuer: issuer.issuer,
      authorization_endpoint: issuer.authorization_endpoint,
      token_endpoint: issuer.token_endpoint,
      response_types_supported: issuer.response_types_supported,
      userinfo_endpoint: this.userinfo_endpoint,
    });
  }

  async discover() {
    return await Issuer.discover(this.discovery_url);
  }
}

const idp = new IdP();
idp.initiate();

3.2 Request an Authorization Code

Call the authorization endpoint to start the authorization flow. Use of Proof Key for Code Exchange (PKCE) is optional for confidential clients.

async authorize() {
  const codeVerifier = generators.codeVerifier()
  const codeChallenge = generators.codeChallenge(codeVerifier)
  const state = generators.state()

  this.storeAuthState(state, codeVerifier)

  return this.client.authorizationUrl({
    scope: this.scope,
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
    state: state,
  })
}

3.3 Exchange the code for tokens

After a successful IdP sign-in, code is generated and redirected back to the configured redirect_uri. Next, the token endpoint is called by the server along with the Qlik Sense SaaS OAuth client credentials. Once validated, Qlik Sense SaaS returns a new token set.

async exchangeForToken(req) {
  // Grab params from callback like "code" and "state"
  const params = this.client.callbackParams(req)
  const [storedState, storedVerifier] = this.shiftAuth()

  // Pass the stored state and code verifier to validate the response
  return this.client.oauthCallback(`${host}/login/callback`, params, { code_verifier: storedVerifier, state: storedState })
}

3.4 Calling Qlik Sense SaaS APIs with the token

The obtained token is be saved by the server. This token can be used to call Qlik Sense SaaS APIs.

async getUserInfo(accessToken) {
    return this.client.userinfo(accessToken)
}
Was this page helpful?