Embedding Preset Dashboards Into Your Application

Embedding dashboards offers a lot of customization options to fit your security and UI needs. Some programming is required, but the process is quite straightforward. These steps should get you well on your way to providing valuable insights to your users.

Step 0: Gather the Preset asset information

In the sub-menu, select Embed Dashboard

Screen_Shot_2022-04-01_at_12 59 31_PM

If you like, you can set the domains that will be allowed to embed the dashboard. When you are ready, click Enable Embedding.

Screen_Shot_2022-04-01_at_1 04 48_PM

Note: Leaving the Allowed Domains field empty will allow embedding from any domain.

You will be shown your Embedded Dashboard ID, Superset Domain, Workspace ID, and Team ID, which you will need for the following steps.

Screen Shot 2022-08-31 at 10 30 36 AM

Step 1: (Back-end) Creating Guest Tokens

A Guest Token authenticates an end user to access an embedded dashboard. Guest tokens are created by calling the Manager endpoint POST https://manage.app.preset.io/api/v1/teams/<TEAM_ID>/workspaces/<WORKSPACE_ID>/guest-token/ from your back-end service.

To make this request, you will first need to authenticate with the Preset API and get an access token. Access tokens have a short lifetime of a few hours, so in a long-running service, they’ll need to be refreshed periodically using your API Key.

⚠️ Important! Token creation must only be done in a trusted back-end execution context. Never expose your Preset API Key or your Preset Access Token!

A python example creating a Guest Token:

  payload = {
	  "user": {
	    "username": "example_username",
	    "first_name": "First",
	    "last_name": "Last"
	  },
	  "resources": [{
	    "type": "dashboard",
	    "id": <EMBEDDED_DASHBOARD_ID>
	  }],
	  "rls": []
	}

	response = requests.post(
		"https://manage.app.preset.io/api/v1/teams/<TEAM_ID>/workspaces" +
		"/<WORKSPACE_ID>/guest-token/",
		data=payload,
		headers={ "Authorization": my_preset_access_token }
	).json()

  guest_token = response["data"]["payload"]["token"]

Explanation of the fields used in the /guest-token endpoint:

For context, here is an example payload which authenticates a user to access two dashboards. The user has three RLS rules applied to them:

{
  "user": {
    "username": "grace_hopper",
    "first_name": "Grace",
    "last_name": "Hopper"
  },
  "resources": [
    { "type": "dashboard", "id": "7dc26b42-fd38-4965-8f60-e156ae233f6d" },
    { "type": "dashboard", "id": "d12678ae-b001-4f97-9822-a6bdf893e97c" }
  ],
  "rls": [
    { "clause": "username = 'grace_hopper'" }, // this rule applies to all datasets in the workspace
    { "dataset": 16, "clause": "environment = 'production'" },
    { "dataset": 42, "clause": "state = 'published'" }
  ]
}

Step 2: Supply Guest Tokens to your application front-end

The token created by the back-end will need to be passed to the front-end before your end user can view a dashboard.

You can perform this transfer in whatever way is appropriate for your application. The typical way is to expose an internal HTTP endpoint that authenticates your user, and creates and returns the guest token.

Here is an example python/flask endpoint building on the example from before:

@app.route("/guest-token", methods=["GET"])
@login_required
def get_guest_token():
  payload = {
	  "user": {
	    "username": g.user.username,
	    "first_name": g.user.first_name,
	    "last_name": g.user.last_name
	  },
	  "resources": [{
	    "type": "dashboard",
	    "id": <EMBEDDED_DASHBOARD_ID>
	  }],
	  "rls": [
	    { "clause": f"user_id = '{g.user.id}'" }
	  ]
	}

	token_response = requests.post(
		"https://manage.app.preset.io/api/v1/teams/<TEAM_ID>/workspaces" +
		"/<WORKSPACE_ID>/guest-token/",
		data=payload,
		headers={ "Authorization": preset_access_token }
	).json()

  return token_response["payload"]["token"]

This is the place to add access control code!

Your code can decide which users should be granted guest tokens. You can also define row-level security rules in the rls parameter to dynamically determine the data that will be displayed to each user.

You will need to determine what the rules should be for your unique application, dashboard, and dataset, so that only the appropriate data will be displayed to your users.

The RLS rule defined above shows how you could filter dashboard data per-user based on their id. For another example, if your users belong to an organization and should only see their organization’s data, you might write an RLS rule like:

{ "clause": "organization = {user.organization}" }

Step 3: (Front-end) Install the Superset Embedded SDK

From NPM:

npm install --save @preset-sdk/embedded

From a CDN:

You can load the SDK as a script in your HTML, if preferred. The SDK will be available as presetSdk globally:

<script src="https://unpkg.com/@preset-sdk/embedded"></script>

Step 4: Embed the dashboard using the SDK

When using ES6 imports or a build tool:

import { embedDashboard } from "@preset-sdk/embedded";

embedDashboard({
  id: <EMBEDDED_DASHBOARD_ID>,
  supersetDomain: <SUPERSET_DOMAIN>,
  mountPoint: document.getElementById("my-superset-container"), // any html element that can contain an iframe
  fetchGuestToken: () => fetchGuestTokenFromBackend(),
  dashboardUiConfig: { hideTitle: true }, // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
});

Using a script tag with CDN:


<script>
	presetSdk.embedDashboard({
	  id: <EMBEDDED_DASHBOARD_ID>,
	  supersetDomain: <SUPERSET_DOMAIN>,
	  mountPoint: document.getElementById("my-superset-container"), // any html element that can contain an iframe
	  fetchGuestToken: () => fetchGuestTokenFromBackend(),
	  dashboardUiConfig: { hideTitle: true }, // dashboard UI config: hideTitle, hideTab, hideChartControls (optional)
	});
</script>

You may pass the following options to embedDashboard:

{
	hideTitle: boolean
	hideTab: boolean
	hideChartControls: boolean
}

embeddedDashboard() asynchronously returns an Embedded Dashboard object. You can call unmount() on this object to clean up an embedded dashboard, and its timers and other effects, from the page.

Sizing the iframe

You can get your embedded dashboards looking a bit more seamless by resizing the iframe so that the browser sizes the content window appropriately. The getScrollSize() method asynchronously returns the full width and height of the embedded dashboard page.

Example making the iframe poll the embedded page to fit its content:

const myDashboard = await embedDashboard();

setInterval(async () => {
	const { width, height } = myDashboard.getScrollSize();
	// imaginary setCSS function. Replace with  whatever method of styling is standard in your application.
	setCss(`
		.embedded-superset iframe {
			width: ${width};
			height: ${height};
		}
	`);
}, 1000);

Security: Preparing your system for embedding

A strong system will have safeguards built in at multiple levels. With that in mind, it is important to take whatever protective steps you can, when using embedded dashboards to expose data outside your organization. The following precautionary measures are advised:

More on embedded authentication

A Preset Guest Token is what enables your users to access embedded Preset resources such as dashboards without having to log in to Preset normally. The Guest Token is used for all Workspace API calls made while viewing an embedded dashboard. It contains user profile data and all the permissions of the user.

Guest tokens have a short lifetime of 5 minutes, and need to be refreshed regularly. To accomplish this, the frontend SDK will call fetchGuestToken to get a new token.

Guest tokens have no ties to the Preset user who set up your embedded dashboard. The permissions your application assigns a guest token at creation are the full set of permissions that the end user will have.

Our design process is open source! For more details on the technical processes involved in embedded authentication, check out the original embedded dashboard proposal on GitHub.