Search results

Row-Level Security(RLS)

Bold BI supports Row-Level Security (RLS) to ensure users only access data they are authorized to see.

RLS can be implemented in two ways:

  • Data Filters - Filter rows dynamically at the data source level.
  • Custom Attributes - Pass user/tenant attributes to dynamically tailor data access.

Data Filter

What is it?

Row-level security can be enforced by passing an embed_datasource_filter attribute in the embed token. This ensures filtering is applied server-side, securely, and without exposing filter logic to end users.

Why use it?

  • Enforces per-user data access securely.
  • Filters are hidden from users and no tampering possible.
  • Supports `URL Parameters` and `Dashboard Parameters`.

Example: Token Generation with Data Filter

Pass data filters via embed_datasource_filter in the token generation method to enforce row-level security by filtering data dynamically and use this token in frontend to render the dashboard.

Node

const crypto = require('crypto');
const https = require('https');
const http = require('http');
const url = require('url');

app.post('/tokengeneration', function (req, res) {
    const serverUrl = "<Bold BI Server URL>";
    const siteIdentifier = "<Bold BI Server Site Identifier>";
    const dashboardId = "<Dashboard Id>";
    const userEmail = "<User Email>";
    const embedSecret = "<Embed Secret Key>";

    // Define row-level filter
    const filter = "[{shipCountry=India}]";

    const serverApiUrl = serverUrl + "/api/" + siteIdentifier;
    let queryString = "embed_nonce=" + crypto.randomUUID();
    queryString += "&embed_dashboard_id=" + dashboardId;
    queryString += "&embed_user_email=" + userEmail;

    // Add filter
    queryString += "&embed_datasource_filter=" + filter;

    // Sign query
    const embedSignature = "&embed_signature=" + getSignatureUrl(queryString, embedSecret);
    const embedDetailsUrl = "/embed/authorize?" + queryString + embedSignature;

    const serverProtocol = url.parse(serverApiUrl).protocol === 'https:' ? https : http;
    serverProtocol.get(serverApiUrl + embedDetailsUrl, function (resultContent) {
        let str = '';
        resultContent.on('data', chunk => str += chunk);
        resultContent.on('end', function () {
            const resultJson = JSON.parse(str);
            if (resultJson?.ApiStatus && resultJson.Data?.access_token) {
                res.json({ access_token: resultJson.Data.access_token });
            } else {
                res.status(500).json({ error: "Failed to generate embed token" });
            }
        });
    });
});

function getSignatureUrl(queryString, embedSecret) {
    const hmac = crypto.createHmac('sha256', Buffer.from(embedSecret));
    return hmac.update(queryString).digest('base64');
}

Filter Syntax Examples

Scenario Query
Single Filter &embed_datasource_filter=[{&Param=Value}]
Multiple Filters &embed_datasource_filter=[{&Param1=Value1&Param2=Value2}]
List Format (IN) &embed_datasource_filter=[{&Param=IN(Value1,Value2)}]

Note: Filters must be enclosed in [] square brackets and {} curly braces. You can also achieve RLS for custom columns using dashboard parameters.

Custom Attribute

What is it?

Custom Attributes are name–value pairs that can be defined at the user, group, or site level. It can be enforced by passing an embed_custom_attribute attribute in the embed token. They allow dashboards to dynamically adjust queries, expressions, or data source connections to enforce RLS.

Why use it?

  • Tailor data access by user role, department, or tenant.
  • Dynamically switch data source connections (e.g., multi-tenant databases).
  • Use one dashboard template for multiple tenants.

Learn More About Custom Attribute: For detailed examples of configure and using custom attributes in dashboard, refer to Custom Attribute Usage.

Example: Token Generation with Custom Attribute

In this scenario, two users access the same dashboard with different databases sharing the same schema. We configured a custom attribute with the database name DB1 in the data source connection of the Bold BI server. In embedding, we dynamically assign a different database, DB2, using the embed_custom_attribute parameter, and the dashboard is rendered with the specified database details.

Note: Explore our demo to see how RLS is achieved with custom attributes.

Node

app.post('/tokengeneration', function (req, res) {
   const serverUrl = "<Bold BI Server URL>";
   const siteIdentifier = "<Site Identifier>";
   const dashboardId = "<Dashboard Id>";
   const userEmail = "<User Email>";
   const embedSecret = "<Embed Secret Key>";

   // Define custom attribute
   const customAttribute = '[{"database_name":"DB2"}]';

   const serverApiUrl = serverUrl + "/api/" + siteIdentifier;
   let queryString = "embed_nonce=" + crypto.randomUUID();
   queryString += "&embed_dashboard_id=" + dashboardId;
   queryString += "&embed_user_email=" + userEmail;

   // Add custom attribute
   queryString += "&embed_custom_attribute=" + customAttribute;

   // Sign query
   const embedSignature = "&embed_signature=" + getSignatureUrl(queryString, embedSecret);
   const embedDetailsUrl = "/embed/authorize?" + queryString + embedSignature;

   const serverProtocol = url.parse(serverApiUrl).protocol === 'https:' ? https : http;
   serverProtocol.get(serverApiUrl + embedDetailsUrl, function (resultContent) {
       let str = '';
       resultContent.on('data', chunk => str += chunk);
       resultContent.on('end', function () {
           const resultJson = JSON.parse(str);
           if (resultJson?.ApiStatus && resultJson.Data?.access_token) {
               res.json({ access_token: resultJson.Data.access_token });
           } else {
               res.status(500).json({ error: "Failed to generate embed token" });
           }
       });
   });
});

function getSignatureUrl(queryString, embedSecret) {
   const hmac = crypto.createHmac('sha256', Buffer.from(embedSecret));
   return hmac.update(queryString).digest('base64');
}

Examples:Custom Attribute Syntax

Scenario Syntax Example
Single Attribute [{"Attribute_Name":"Value"}] &embed_custom_attribute='[{"database_name":"DB1"}]'
Multiple Attributes [{"Attr1":"Value1","Attr2":"Value2"}] &embed_custom_attribute='[{"department":"IT","name":"David"}]'
List Format (IN) [{"Attribute_Name":"IN('Value1','Value2')"}] &embed_custom_attribute='[{"department":"IN('CSE','EEE')"}]'

Benefits of Custom Attributes

  • Secure Data Access: Ensures tamper-proof, row-level security for user-specific data.
  • Dynamic Personalization: Restrict data access based on user roles, departments, or tenants.
  • Multi-Tenant Efficiency: Reuse a single dashboard template across multiple tenants with different databases.

Decision Matrix: Data Filters vs Custom Attributes

Scenario Use Data Filter Use Custom Attribute Recommendation
User-Specific Data Filtering If you need to filter data for individual users based on static or dynamic criteria (e.g., user location, department), Data Filters are the best choice. Custom Attributes are more useful when tailoring data by user attributes (e.g., role, tier). Enables flexible, dynamic control. Use Data Filters if criteria map directly to fields. Use Custom Attributes if filtering depends on user identity metadata.
Role-Based Access Control (RBAC) Works for simple, fixed role sets (e.g., Admin, User). Harder to scale for many roles or complex orgs. Great for dynamic role-based filtering. User attributes (roles, departments, groups) drive access automatically. Custom Attributes are better for scalable RBAC. Data Filters only fit basic role checks.
Complex User Groups Effective if groups can be predefined and filter values remain static. Handles dynamic, overlapping, or nested groups (e.g., contractors, multi-tenant groupings). Custom Attributes are more flexible unless groups are small and static.
Multi-Tenant Scenarios Requires manual filter management for each tenant, which is hard to scale. Ideal in multi-tenant environments where each tenant may have a different data or access control. Easily pass different values for each tenant. Custom Attributes are the clear choice for clean, scalable isolation.
Easier Implementation Straightforward for simple rules like filtering by department or country. Minimal setup required. Requires attribute infrastructure and more backend logic. Start with Data Filters for a quick prototype; move to Custom Attributes as complexity grows.