When embedding a Tableau viz into an application, we are very often asked about passing parameters in to the viz to filter down information. This post is about a few methods of implementing this behavior, and the security implications of each of them.
I’ll start by saying, to do any of this securely, you need EVERY resource you are working with to be using the HTTPS protocol (latest TLS version). If anything is not HTTPS, you could be passing important information in the clear.
There are three methods of setting a Tableau Parameter on a Tableau Server viz:
- Putting the Parameter value directly in the URL using a name value pair
- Setting the Parameter value using the JS API options object in the constructor method. This actually does the equivalent of #1 and puts the values in the URL
- Use changeParameterValueAsync() method of the JS API.
Each has its own benefits and downsides.
The “GET” Methods
Methods 1 and 2 both work prior to the viz loading, which means they are more efficient and direct. However, they both use the GET method in the URL, which requires thinking about about potential “leaks” of the information.
I will admit to being misinformed until researching this issue. I thought that GET parameters passed in the URL were insecure even using HTTPS. This is not the case — the full URL, as well as the POST data, is completely secure in transmission using the HTTPS protocol.
So where are the risks? Because the values are in the URL, at the endpoints of the transmission they can be written down in the clear.
- If you have the parameters on a Viz that is loaded directly (i.e. viewed through the Tableau Server UI rather than embedded into another page), the URL will be written down in the user’s browser history
- Any external content that is loaded by the viz will receive the full URL as a “Referrer” header. The only place this would typically happen is the Tableau mapping server, maps.tableausoftware.com. But if you embed some other web content into a Dashboard, it could definitely happen. That should all be HTTPS content as well though.
- The Tableau Server logs themselves will hold the parameters. But, your Tableau Server should be securely behind the firewall with access only granted to administrators. If someone has direct access to the Tableau Server machine, there is a lot more danger than just the URLs being in the logs.
The “POST” Method
The changeParameterValueAsync() method is more programmatic, but can’t be used until after the viz has loaded at least once. It uses the POST method which is less “leaky” than GET. POST data shouldn’t be logged down, nor does it appear in any referrer links.
The downside is the delay required to load a viz in a “blank state” then send the update. The best practice here would be to have a “cover div” to keep the viz from being shown until the changeParameterValueAsync() method is finished, then take away the “cover div” in the callback function.
Obfuscating the Keys and the Values
What can we do to solve this issue? The standard answer for Tableau is to use Row Level Security, where the user is authenticated in Tableau Server and then tied into a security table in the database so that the user only ever sees data they have access rights to.
But let’s try and propose a solution that still allows passing a parameter. If you were able to generate an encrypted and randomized token applicable for a given user’s session, you could theoretically have the reverse proxy (which should always be sitting between the outside world and the Tableau Server machine itself) substitute in the appropriate URL parameters in.
The workflow would look something like this:
- User makes request to web application where Tableau Viz is embedded
- A token is generated and appended to the URL of the Tableau viz (for example: https://tabserver.yourcompany.com/workbook/SomeView?tk=JsnfsfiJVJs9eu394ujvso39-39wur0sjfob3-usef8s0fj)
- When the Tableau Viz is loaded by the JS API constructor, a request is made to the reverse proxy server, which then decodes the token into the actual URL parameter that is desired (ex. https://tabserver.yourcompany.com/workbook/SomeView?uname=someuser.whatever)
- Tableau Server loads the viz with the parameter in the clear
Some precautions would need to be taken here as well:
- The reverse proxy should throw away any URLs that attempt to pass the real name of the Tableau Parameter on the URL. We don’t want outside users to ever be able to ATTEMPT setting this value.
- The tokens need to be invalidated after each use.
If somehow the tokens were already available in the end database in a way that could link to the data tables, you could potentially just use the tokens directly by doing the right set of JOINs and Calculated Fields / Filters in Tableau Desktop. This would be like Row Level Security using tokens. However, you would have to make sure the tokens were thrown away ASAP and so randomized as to impossible to brute force.