cancel
Showing results for 
Search instead for 
Did you mean: 
ILLIA
Sisense Team Member
Sisense Team Member

SisenseJS silent login approach

Disclaimer: Please note that this blog post contains one possible custom workaround solution for users with similar use cases. We cannot guarantee that the custom code solution described in this post will work in every scenario or with every Sisense software version. As such, we strongly advise users to test solutions in their environment before deploying them to ensure that the solutions proffered function as desired in their environment. For the avoidance of doubt, the content of this blog post is provided to you "as-is" and without warranty of any kind, express, implied, or otherwise, including without limitation any warranty of security and or fitness for a particular purpose. The workaround solution described in this post incorporates custom coding, which is outside the Sisense product development environment and is, therefore, not covered by Sisense warranty and support services.

Description:

This article describes how to authenticate Sisense users on the parent application without any page refreshes or redirects. Starting from L2023.11.1, Sisense returns Sisense.JS libraries not depending on authentication. SSO flow will work with SSO.newReturnToValidationBehaviour enabled in Admin -> Server & Hardware -> System Management -> Configuration -> {5 clicks on logo} -> Base Configuration, however, it will redirect users back to the parent application causing page refresh which could be not suitable in terms of user experience.

Prerequisites: 

Basic JS knowledge and Sisense.JS embedding sample (for example, from here: https://sisense.dev/guides/embeddingCharts/jsGettingStarted.html#example)

Solution: 

This logic check if we are authenticated in Sisense, if not - it will get the SSO login URL from the response and create an Iframe with that URL as a source. Once Iframe is loaded and the Sisense session is generated - we will remove Iframe from the page and proceed with Sisense.JS logic. Here is an example of a silent login function:

 

const silentLogin = async () => {
      let isauth = await fetch(url + '/api/auth/isauth', {credentials: 'include'})
      let isauthJson = await isauth.json()
      if (!isauthJson.isAuthenticated && isauthJson.ssoEnabled) { //Check if we are not logged in and SSO is enabled
        iframesrc=isauthJson.loginUrl + '?return_to=/api/auth/isauth'
      }

      var iframe = document.createElement('iframe');
      iframe.src=iframesrc ? iframesrc : url + '/api/auth/isauth'; // set SSO login URL if returned
      iframe.style.display = 'none'; // Hide iframe initially
      document.body.append(iframe);

      // Wait until page is loaded
      iframe.onload = function () {
        // Page is loaded, now remove the iframe
        document.body.removeChild(iframe);
        startSisense()
      };

    }

 

 

Once we authenticate the user in an Iframe, we can append the Sisense.JS script and once it is loaded on the page - we run further logic: 

 

const startSisense = async () => {

      const sisensejs = document.createElement('script')
      sisensejs.src=url + '/js/sisense.v1.js'
      sisensejs.onload = async () => {
        await renderdash()
      }
      document.head.append(sisensejs)
    }

 


renderdash() in this case is our function where we connect to Sisense and render assets. Here is an example of full HTML code used for the example.

Please note that the host and dashboard ID are coming from the local /config endpoint raised on my side, for local testing you need to replace those values manually or point to your configuration file. 

 

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>
  <div id="sisenseApp" style="display: flex; width:100%">
  </div>
  <div id="main" style="display: flex; flex-direction: column; justify-content: center; width: 80%"></div>
  <div>
    <div id="filters" style="width: 20%; min-width: 250px; min-height: 300px; height: 100%"></div>
  </div>

  <script type="text/javascript">

    let app
    // Please make sure CSRF is disabled and your app domain is added to CORS allowed list
    const url = config.host //this value is from local config file, please specify host manually here or point to your configuration file
    const dashboardId = config.defaultDashboardSisenseJS //this value is from local config file, please specify dashboard ID manually here or point to your configuration file
    let iframesrc=''
    const silentLogin = async () => {
      let isauth = await fetch(url + '/api/auth/isauth')
      let isauthJson = await isauth.json()
      if (!isauthJson.isAuthenticated && isauthJson.ssoEnabled) { //Check if we are not logged in and SSO is enabled
        iframesrc=isauthJson.loginUrl + '?return_to=/api/auth/isauth'
      }

      var iframe = document.createElement('iframe');
      iframe.src=iframesrc ? iframesrc : url + '/api/auth/isauth'; // set SSO login URL if returned
      iframe.style.display = 'none'; // Hide iframe initially
      document.body.append(iframe);

      // Wait until page is loaded
      iframe.onload = function () {
        // Page is loaded, now remove the iframe
        document.body.removeChild(iframe);
        startSisense()
      };

    }

    const startSisense = async () => {

      const sisensejs = document.createElement('script')
      sisensejs.src=url + '/js/sisense.v1.js'
      sisensejs.onload = async () => {
        await renderdash()
      }
      document.head.append(sisensejs)
    }

    const renderdash = async () => {

      if (window.Sisense) {
        window.Sisense = {}
      }
      const main = document.getElementById("main")
      if (!window.Sisense.app) {
        app = await Sisense.connect(url, true)
        window.Sisense.app = app
      }
      const dash = await app.dashboards.load(dashboardId)


      window.Sisense.widgets = []
      const widgetsRaw = await fetch(url + "/api/v1/dashboards/" + dashboardId + "/widgets?fields=oid,title", {
        method: 'GET',
        credentials: 'include'
      })
      let widgets = await widgetsRaw.json()
      if (widgets.length) {
        widgets.forEach((w) => {
          window.Sisense.widgets.push(w)
          const widgetElement = document.createElement('div');
          //widgetElement.style.minHeight = '400px'
          widgetElement.style.width = '400px'
          widgetElement.style.height = '400px'
          widgetElement.setAttribute("id", "widget_" + w.oid);
          let title = document.createElement('p')
          title.innerText = w.title
          main.append(title)
          main.append(widgetElement)
          dash.widgets.get(w.oid).container = document.getElementById("widget_" + w.oid)
        })
      }
      dash.renderFilters(document.getElementById("filters"));
      dash.refresh()
    }


    silentLogin()
  </script>

</body>


</html>

 

As a result, we can see the full trace of our flow in a Network tab of the browser:

ILLIA_0-1716559120698.png

 

Rate this article:
Version history
Last update:
‎06-04-2024 08:36 AM
Updated by: