Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Qlik and ServiceNow Partner to Bring Trusted Enterprise Context into AI-Powered Workflows. Learn More!
Michael_Tarallo
Employee
Employee

Let's see how it is possible to control sheet and object-level access in Qlik Cloud, specifically when organizations want to show/hide specific assets in an application based on the group membership of the current user that is accessing the application. 

 

2023-06-05_13-06-48.pngHey guys, it's been awhile since we had a guest blogger on, so today I am pleased to introduce you to Daniel Pilla. Daniel is a Master Principal Analytics Platform Architect at Qlik and is part of the Presales organization. He has been with Qlik for 8 years, and specializes in integration, architecture, embedding, and security. Take it away Dan!

 

 

 

Sheet and object-level access control in Qlik Cloud

This is a relatively common request, especially from customers coming from Qlik Sense Enterprise Client-Managed. The use case is when organizations want to show/hide specific assets in an application based on the group membership of the current user that is accessing the application. Note that this is in no way a strategy or solution for data security (which is handled with section access), but rather serves as a potential design pattern for custom tailoring apps for specific groups of users.

Example Scenario

Let’s assume a customer has a global sales application. That application contains sheets that are designed for specific product group sales that not every sales representative sells. The customer wants to show the product-specific sheets only to the sales representatives that sell those respective products. If the user contains the group “Product Group A” then they should see the “Product Group A Analysis” sheet, and likewise if the user contains the group “Product Group B” then they should contain the “Product Group B Analysis” sheet.

Michael_Tarallo_0-1685984516021.png

 

Solution

To achieve this in Qlik Cloud, we can use the Advanced Analytics connector, which in essence is a RESTful server-side extension. This connector offers the ability to connect to RESTful services in real-time from both the load script and from the front-end (charts and expressions). We can use this connector to connect directly to the Qlik Cloud APIs to fetch the groups of the current user, return those groups as a pipe-delimited string, and then use those groups in a show condition expression.

Michael_Tarallo_1-1685984516061.png

 

Setup

Prerequisites:

  • The Advanced Analytics connector is going to be making API calls to Qlik Cloud on behalf of the logged in user. This means that you must have a user with the “Developer” role assigned as well as an API key issued to that user.
  • The Creation of groups setting must be enabled in the Console under Settings > Feature control

Michael_Tarallo_2-1685984516085.png

 

  • Ensure that there are groups available to the user that you are testing for in the tenant. To check this, you can enter the following into the browser, replacing {tenant} and {region} accordingly: https://{tenant}.{region}.qlikcloud.com/api/users/me -- There, you will find the assignedGroups array which contains the groups that are assigned to the logged in user.

Connector Setup:

  1. Import the sample application attached to this page.
  2. Open the application and navigate to the load script.
  3. Under Data connections, select Create new connection and select Advanced Analytics.
  4. For URL, fill in your own tenant for URL followed by ‘/api/v1/users’
    1. https://{tenant}.{region}.qlikcloud.com/api/v1/users
  5. Change the Method to GET.
  6. Under Query Parameters, add a parameter with the Name of ‘filter’ and the Value should resemble the following, where {subject} is an existing user subject for the filter so you can test whether the connection is operational:
    1. {subject co “{subject}”}
    2. In this example, the user I am using has a REALM value. Note that you will have to escape the backslash with an extra backslash, e.g., QLIK-POC\dpi needs to be QLIK-POC\\dpi

Michael_Tarallo_3-1685984516111.png

 

Michael_Tarallo_4-1685984516135.png

 

  1. Within Authorization, change the Authorization Method to Bearer Token.
  2. Under Token Scheme, select Bearer.
  3. For Bearer Token, enter in the API key mentioned as a prerequisite above.

Michael_Tarallo_5-1685984516148.png

 

  1. Within Response Table, for Name of Returned Table enter the value of ‘data’. Note that this value is only really relevant for the load script, but the field is required to be populated nonetheless.
  2. Under Table Path (JMESPath), enter in the value of ‘data’. Note that this is the name of the JSON object containing the data returned from `api/v1/users` and contains source of data that we require from the payload.
  3. Within Response Fields, deselect Load all available fields. This is so we can customize the value that is returned.
  4. Within Response Table, under Table Fields (JMESPath), enter a new Name value as ‘groups’, then enter the Value of ‘join(‘|’,assignedGroups[*].name)’. This will concatenate all of the values of the ‘assignedGroups’ array returned by the API into a pipe delimited string. This function is a part of the JMESPath query language that is supported by the Advanced Analytics connector. To learn more, you can refer to: https://jmespath.org/tutorial.html.

Michael_Tarallo_6-1685984516198.png

 

  1. Leave the remaining settings untouched.
  2. Set the Name of the connection as ‘Get Groups’. Note in this case this is important because the name of the connection is directly referenced in the expression of the accompanying sample app.

Michael_Tarallo_7-1685984516212.png

 

  1. Test the connection and ensure that it is operational.

 

Sample App Testing:

The sample application includes three sheets:

  1. Get Current User Groups – this sheet displays the current groups of the logged in user.
  2. Product Group A Analysis – this sheet has a commented out calculation condition to only show the sheet if the user contains the group ‘Product Group A’.
  3. Product Group B Analysis – this sheet has a commented out calculation condition to only show the sheet if the user contains the group ‘Product Group B’.

The application transforms the OsUser() result into the subject format, looks up the user, gets the groups, and returns them as a pipe-delimited string. You can find this process defined in the vUserSub and vUserGroups variables.

To test the application, first confirm that the first sheet returns your user groups. If it does, you can modify the sheet calculation conditions on the latter two sheets to your desired group names that you want to show based on.

Michael_Tarallo_8-1685984516312.png

 

Modify the expression by uncommenting it and adding in your desired group name (ensured it is enclosed by pipes so as to not partially match another group name):

Michael_Tarallo_9-1685984516333.png

 

In my example, I am a member of the group `Product Group A’ and not `Product Group B’, so while in edit mode, I see the following, confirming the ‘Product Group B Analysis’ is hidden from my view:

Michael_Tarallo_10-1685984516354.png

 

Exiting edit mode, I now see:

Michael_Tarallo_11-1685984516371.png

Additional Notes

  • If users have edit-level access or greater to the application where this method is deployed, when in “Edit” mode, they will be able to see that the hidden sheet(s) exist. The user could then duplicate that sheet and remove/alter the show condition so that they could see the sheet. This is not a data security risk, as this technique only focuses on cosmetic app design, however it should be noted that if it is desired that the users cannot have access to these sheets then they must not have any roles that allow for edit-level access including “Can manage”, “Can contribute”, and “Can edit”.
  • This solution relies on API calls being made by the owner of the API key.
    • This user must:
      • Continue to be exist
      • Continue to have the “Developer” role
      • Ensure that the API key does not expire and/or is rotated to prevent downtime

  •  As this solution is making calls on behalf of a single user as users are leverage the application, there is the potential for rate-limiting at the Users API. The current rate limit of the Users API is 1,000 calls per minute.

  • The Advanced Analytics connector function call in the sample app leverages the "ShouldCache":"False" setting in the vUserGroups variable. This ensures that the user’s groups are not cached by the engine, however it makes more calls to the APIs. If you are experiencing or are concerned about rate limiting, this setting can be removed.
Tags (2)
11 Comments
Or
MVP
MVP

One more note - assuming the functionality it similar to Enterprise, this does not actually control access. As stated in the lead, show/hide is not meant to be used for security, and (at least in Enterprise) any user with the ability to duplicate sheets can duplicate the sheet in question, remove the condition, and use the sheet.

3,612 Views
Daniel_Pilla
Employee
Employee

Hi @Or ,

In most cases, the bulk of users in a deployment do not the ability to edit applications, especially where this technique would be leveraged. Take for an example a published application in a Managed space, where all users have "Can view" access to the space. Because the users do not edit-level access, they will not be able to view, duplicate, or edit the hidden sheet(s). I would define that as access control. Now, in the case where users can edit the application and thereby duplicate the sheet and remove the condition--they would not be able to somehow access data they otherwise couldn't get access to--they would just see a sheet that wasn't designed for them. While I hear your point that this isn't true access control in the strictest sense, if leveraged appropriately it can be. I will make a note in the article above to further clarify this point.

 

Cheers,

3,570 Views
Or
MVP
MVP

@Daniel_Pilla  I have no idea how many users in deployments would typically have Duplicate permissions, but anyone with that option will be able to get to the hidden sheet should they want to (at least in Enterprise, I'm not an expert on how this works in Qlik Cloud) by entering edit mode in one of their duplicated/private sheets and then selecting the hidden sheet and duplicating that. It's not exactly something that's immediately obvious to most people, but it does preclude show/hide from being used as security for information contained within said sheets.

That said, the article already notes that this is not meant to be used for security, so my comment was just adding a note about the fact that under certain circumstances, the contents of the sheet will not necessarily be hidden, so it's best practice not to put anything sensitive into that sheet (text objects, images, etc) if some people can duplicate it.

0 Likes
3,563 Views
Daniel_Pilla
Employee
Employee

Hi @Or ,

The Additional Notes section of the article above has been updated to add a note about your comment.

 

Cheers,

3,553 Views
rwunderlich
Partner Ambassador/MVP
Partner Ambassador/MVP

Hi @Daniel_Pilla After completing steps 12 &13 above, the "Test Connection" and "Save" options are always greyed out. That is, if deselect "Load all available fields", those options are greyed out no matter what I enter for Table Fields. Any suggestions?

-Rob

2,630 Views
saso70
Partner - Creator II
Partner - Creator II

I have the same problem @rwunderlich  , did you find the solution?

2,355 Views
Daniel_Pilla
Employee
Employee

@rwunderlich , @saso70 ,

Yes, this is a recent bug. You have to create the data connection in the Hub vs the Load script, or you cannot save it. I am unsure what caused this, but @Steven_Pressland owns the issue now and may have an update.

This should fix it for you in the short term. We use it internally and have gone this route.

Cheers,

2,346 Views
Chris_RIC
Partner - Contributor
Partner - Contributor

Hi @Daniel_Pilla 

Can a similar framework be used for app level access?

0 Likes
1,753 Views
DanielCordon
Contributor II
Contributor II

Hi. I have an issue getting properly this information. I posted this one Not-getting-information-from-user-logged-via-Advanced-connector/ . If you can help me with that I'll appreciate a lot! 

Thanks

0 Likes
1,571 Views
Manguirish
Contributor III
Contributor III

I am unable to find this connector when i Create Connection. Is this still available or is it specific to any kind of tenant?

0 Likes
1,126 Views