Define base connection roles
When generating embed requests, set the connectionRoles parameter to either No Access or Viewer. This sets the default level of access for the connection and ensures that access to data must be granted on an individual user basis.
Send connection roles on every embed request
When a user creates an embed session, the connectionRoles on the latest request acts as the source of truth for that user’s connection access. This means:
- A role can be downgraded by a later request (e.g. from Restricted Querier to Viewer).
- A role can be removed entirely if the later request doesn’t mention the connection — either explicitly in
connectionRoles or implicitly in the connection backing the requested contentPath.
If you embed multiple pieces of content on the same page (for example, a dashboard and a workbook in separate iframes), include an explicit connectionRoles object on every request. Each iframe generates its own embed login request, and a request that omits connectionRoles will overwrite the access granted by the others.
For example, imagine a page that embeds:
- A workbook backed by connection A, which requires at least Restricted Querier access
- A dashboard backed by connection B, which only requires Viewer access
If the dashboard’s embed request only specifies connectionRoles for connection B, the user’s role on connection A will be deleted as soon as that request resolves — and the workbook will lose access. To avoid this, send connectionRoles for both connection A and connection B on both the workbook and dashboard embed requests.
Leverage user attributes to control data access
To ensure appropriate data access for users, best practice is to leverage user attributes to systematically filter data.
- Access filters, or row-level security, allow you to restrict the rows of data a user can access within a topic. Access filters apply the values assigned on a user attribute to the
WHERE clause of every SQL query a user runs, filtering out to only the data designated to that user.
- Access grants define topic- and field-level permissions for users
Implement security for multi-tenant instances
Segmenting data using hidden dashboard filters is not a secure practice.
Typically, companies choose one of the following strategies to set up multi-tenant customer data:
- Row-level security - If all of the data is inside one table, you can assign a user attribute per user and client and use it as an access filter. Specifically make sure to set up a default access filter to control in Omni with
default_topic_access_filters. Note that input columns automatically enforce access filter fields in their mapping keys to prevent cross-tenant data leakage.
- Schema level security - If each client is in a separate, identical schemas then you can leverage dynamic schemas.
- Database level security - If each client is in a separate database and the schemas are identical across databases, you can leverage dynamic database environments.
- Model-level isolation - If each client needs a tailored view of the same base model, you can use shared extension models to create tenant-specific extensions that inherit core logic while allowing per-client customizations.
Build content on shared topics
Embedded dashboards won’t render correctly if the content you want to embed meets any of the following criteria:
- Content contains fields not included in a topic in the shared model
- Content built on SQL
- Content that contains unpromoted changes to joins in the workbook’s model
To expose non-topic bound or SQL-based content, enable AccessBoost in the content’s Share settings. This has security implications, as you may expose data that you don’t want your embed users to access.
Save content to the Shared hub
Along with the above criteria for building content on topics, embedded dashboards must be saved in your instance’s Shared hub. Dashboards will not render correctly if they are saved in personal folders.
Use unique emails per embed user
Email addresses in embed are used to resolve delivery recipients and apply user attributes. Each embed user must have a unique email to ensure deliveries reach the intended recipient with the expected attributes applied.
- Never mix internal and embed user emails. If you must use the same base email, use the
+ modifier - for example, blob@example.com for the internal user and blob+omniembed@example.com for the embed user.
- Never reuse the same email across different
externalId values. Each embed user should have a unique email to ensure deliveries reach the intended recipient.
- Include the
email parameter when generating the embed session. Without it, email deliveries cannot be mapped back to the embed user and Omni will create a separate email-only user instead.
Create unique embed users when embed users access data in multiple entities
If a physical user in your application has access to data across multiple entities, provision a separate embed user for each entity rather than reusing a single embed user across all of them.
An embed user’s attributes reflect their most recent embed session. Each new session overwrites the previous attributes. If the same embed user is used across entities, whichever entity was accessed most recently determines what attributes that user holds.
Example: A physical user who accesses both acme and globex should have two embed users:
| Physical user | Entity | externalId | Email |
|---|
| user@yourapp.com | acme | user_acme | user+acme@yourapp.com |
| user@yourapp.com | globex | user_globex | user+globex@yourapp.com |
Each embed user gets the user attributes appropriate for its entity. When the user switches between entities in your application, your server generates a new embed URL using the corresponding embed user’s externalId and attributes.
See user attributes and access filters for details on configuring per-entity row-level security.