Qlik Community

Ask a Question

Integration, Extension & APIs

Discussion board where members can learn more about Integration, Extensions and API’s for Qlik Sense.

cancel
Showing results for 
Search instead for 
Did you mean: 
Kalkumar
Partner
Partner

Extension to logout a user from Qliksense

Hello, 

We have been trying to create an extension to logout the user from QlikSense application using Delete Method. 

We referred this link to create our extension https://community.qlik.com/t5/Integration-Extension-APIs/Working-with-logout-API-in-mashup/td-p/1181... .

Our Approach :-

We wrote below code in Visual Studio, instead of using the DELETE method, as a first step to check if our code is working or not we wanted to fetch the logged in user details using the GET method. However, we always get the below response 

 

{"session":"inactive"}

 

 

Our Expected response

 

{
    "userDirectory": "QWERTY",
    "userId": "abc-Name1234",
    "userName": "abc-Name1234",
    "logoutUri": "https://ourcompanydomain.company.com/qps/user"
}

 

 

HTML

 

<!DOCTYPE html>
<html lang="en">
<head>
   
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>  // Copied a random url from google
    <script src="script.js">



    </script>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<h1>Welcome</h1>
<Button type="Button" , ID = "Button" onclick="buttonClickHandler();">Logout</Button>
</body>
</html>

 

 

Javascript (script.js)

 

function buttonClickHandler(){

    console.log('You have clicked the Button fetchBtn')
    const xhr = new XMLHttpRequest();
   // xhr.withCredentials = true;


 
    xhr.open('Get','https://ourcomanydomain.companyname.com/qps/user',true)

    xhr.onprogress = function()
    {

        console.log('On Progress');
    }

    xhr.onload = function(){
        if(this.status === 200 ){
         console.log(this.responseText)
        }
        else 
        {
            console.error("Some Error occured")
        }
    }

  
    xhr.send();
   
}

 

 

Note: We have amended the code, instead of Ajax we used XMLHttpRequest() approach. 

Thanks

Harish

 

 

 

Labels (1)
1 Solution

Accepted Solutions
vegard_bakke
Partner
Partner

In your case, CORS error is actually a step in the right direction. (Even though that are a pain to figure out some times.)

 

Origin
First of all: The error message says: from origin 'http://127.0.0.1:5500'
Is that where you host your test web page? (The one firing the DELETE request?)

The URL for the web page must be whitelisted in the virtual proxy.

Let's say you have your web page on https://www.company.com/qlik, getting Qlik objects from https://qlik.company.com/vproxy/...

Then the virtual proxy 'vproxy' must whitelist 'www.company.com' (no https).


Don't use Access-Control-Allow-Origin: *

When responding to a credentialed requests request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.

(Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)

And since you need to pass the cookie (credentials), I don't think you can, or should, add '*' in your A-C-A-O header.  You need to whitelist all possible domains using the sense server.

 


Don't combine HTTP and HTTPS
Last time I check, Qlik still got confused if your web page was running on HTTP while Sense was running on HTTPS. (It was picking up the protocol from the wrong URL.)

Basically what this means is that both the webserver and Sense must either both run on HTTP, or they must both be using HTTPS.
(Which isn't a bad practice, so I don't think it will be fixed anytime soon.)


Decoding error messages
Just a side note. I have absolutely no problems that you remove the actual domain names form the screen shots. But when debugging CORS problems, these are important.  Could you remove your domains, but insert two dummy sample domains in the next screen shots. Just so that we can dig into the cause?

Here is a working request from https://webapps.qlik.com/bbq/index.html, connecting to https://sense-demo.qlik.com/.

vegard_bakke_0-1627288628281.png

In DevTools - Network - Headers you can see the Response' Origin header, and the reply's Access-Control-Allow-Origin header.

That. And Network - Cookies - Show filtered out cookies, are my main tools for finding out why a connection to Qlik is not working. 

Pay attention to the details. Such as the 's' in 'https', the domain, and the path in the cookie.

vegard_bakke_1-1627289156367.png

 

Happy hunting! 

Vegard 🙂

View solution in original post

5 Replies
vegard_bakke
Partner
Partner

Hi Harish,

 

What happens if you uncomment the `xhr.withCredentials` line?

 

If you don't pass the session cookie, then Qlik won't know who is doing the request. 

 

Also, you might need to include the virtual proxy in the URL (if you logged in through another v.proxy than the default one.)

 

Hope this helps,

Vegard 

Kalkumar
Partner
Partner
Author

Hi @vegard_bakke@vegard_bakke  ,

When we uncomment this part, we get CORS policy error as below.

Kalkumar_0-1626967219252.png

As of now, we have written headers "access-control-allow-origin: *" in our QMC to handle CORS error which we were getting in our browser's developer tool. 

URL 

 

https://ourcompanydomain.company.com/OurVirtualProxy/qps/user"

 

Could you please help us how can we obtain session cookie details and where we can pass it in order to obtain the logged in users session?

Thanks 

Harish 

 

vegard_bakke
Partner
Partner

In your case, CORS error is actually a step in the right direction. (Even though that are a pain to figure out some times.)

 

Origin
First of all: The error message says: from origin 'http://127.0.0.1:5500'
Is that where you host your test web page? (The one firing the DELETE request?)

The URL for the web page must be whitelisted in the virtual proxy.

Let's say you have your web page on https://www.company.com/qlik, getting Qlik objects from https://qlik.company.com/vproxy/...

Then the virtual proxy 'vproxy' must whitelist 'www.company.com' (no https).


Don't use Access-Control-Allow-Origin: *

When responding to a credentialed requests request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.

(Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)

And since you need to pass the cookie (credentials), I don't think you can, or should, add '*' in your A-C-A-O header.  You need to whitelist all possible domains using the sense server.

 


Don't combine HTTP and HTTPS
Last time I check, Qlik still got confused if your web page was running on HTTP while Sense was running on HTTPS. (It was picking up the protocol from the wrong URL.)

Basically what this means is that both the webserver and Sense must either both run on HTTP, or they must both be using HTTPS.
(Which isn't a bad practice, so I don't think it will be fixed anytime soon.)


Decoding error messages
Just a side note. I have absolutely no problems that you remove the actual domain names form the screen shots. But when debugging CORS problems, these are important.  Could you remove your domains, but insert two dummy sample domains in the next screen shots. Just so that we can dig into the cause?

Here is a working request from https://webapps.qlik.com/bbq/index.html, connecting to https://sense-demo.qlik.com/.

vegard_bakke_0-1627288628281.png

In DevTools - Network - Headers you can see the Response' Origin header, and the reply's Access-Control-Allow-Origin header.

That. And Network - Cookies - Show filtered out cookies, are my main tools for finding out why a connection to Qlik is not working. 

Pay attention to the details. Such as the 's' in 'https', the domain, and the path in the cookie.

vegard_bakke_1-1627289156367.png

 

Happy hunting! 

Vegard 🙂

View solution in original post

Kalkumar
Partner
Partner
Author

@vegard_bakke Thank you sharing your knowledge , this helped us a lot. 

 Our mistakes in initial phase of creating logout extension : - 

We were trying to call the DELETE method from our local host (http://127.0.0.1:5500) where as it should be done directly from the DNS. Because DNS from where the user had logged in will have the user/session cookie which is needed to kill the session/user session.

Below is the step by step approach we followed to fix the issue.

 Step 1) Create extension using AngularJS template in the Dev-Hub.

Step 2) JS code (logout.js)

define( ["qlik", "text!./template.html"],
	function ( qlik, template ) {

		return {
			template: template,
			support: {
				snapshot: true,
				export: true,
				exportData: false
			},
			paint: function () {
				return qlik.Promise.resolve();
			},
			controller: ['$scope', function ( $scope ) {
			 NPrintButton.onclick = function retrieveReport(){
				$.ajax({
  					 url:"https://YourCompanyDNS.com/qliksense/qps/user",
  					 type: "DELETE",
  					
  					 success: function (qliksense){
    				 console.log(qliksense);
  						 },
  						 error: function (error){
    					 console.log(error);
  						 }
			});
			}
				
			}]
		};

	} );

Step 3) HTML Code (template.html)

<div qv-extension style="height: 100%; position: relative; overflow: auto;" class="ng-scope">
	{{ html }} 
	
	<!DOCTYPE html>
	<html lang="en">
	<head>

    <script src="logout.js">
    </script>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	</head>
	<body>
	<button type="Button" ID="NPrintButton">Logout</button>
	</body>
	</html>
	
	
</div>

 

Thanks

Harish

vegard_bakke
Partner
Partner

That makes sense! A lot of people mix up where their code is executing. Thinking it is executing on the server, when it it executing in the browser of the user.


The HTML and JavaScript is executed in the browser.  And for the browser tell the Qlik Sever to logout, well as you say, it needs to use the DNS name (or the so called fully qualified domain name, FQDN).

While 127.0.0.1 would refer to the machine where the browser is running. 


Thanks for sharing the example code. That will help people later when having the same issue. 😊👍