Search results

Row-Level Security

Bold BI enables Row Level Security (RLS) to ensure users only access data they are authorized to see, using Data Filter and Custom Attribute. This guide explains how these mechanisms provide secure, user-specific data access for embedded dashboards.

Data Filter

What is it?

Row-level security is achieved server-side by including the embed_datasource_filter attribute in the token generation process. This attribute filters data rows based on user-specific criteria, ensuring secure, tamper-proof access without exposing filter logic to users.

Why use it?

  • Ideal for enforcing user-based data access.
  • Ensures maximum security by hiding filters from users and preventing tampering with filter values.
  • Supports URL parameters and dashboard parameters for flexible row-level restrictions.

Pass data filters via embed_datasource_filter in the token generation method to enforce row-level security by filtering data dynamically and pass 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');

  //Token Generation With Data Filter
  app.post('/tokengeneration', function () {

      var serverUrl = "< Bold BI server URL >";
      var siteIdentifier = "< Bold BI server Site Identifier >";
      var dashboardId = "< Dashboard Id >";
      var useremail = "< Bold BI server user Email >";
      var embedSecret = "< Embed Secret key >";
      var filter = "[{shipCountry=India}]" // Add your filter data

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

      // Filter Query
      queryString += "&embed_datasource_filter=" + filter;
      var embedSignature = "&embed_signature=" + GetSignatureUrl(queryString,embedSecret);
      var embedDetailsUrl = "/embed/authorize?" + queryString+embedSignature;

    var serverProtocol = url.parse(serverApiUrl).protocol == 'https:' ? https : http;
    serverProtocol.get(serverApiUrl + embedDetailsUrl, function (resultContent) {
      let str = '';
      resultContent.on('data', function (chunk) {
          str += chunk;
      });
      resultContent.on('end', function () {
              const resultJson = JSON.parse(str);
              if (resultJson && resultJson.ApiStatus && resultJson.Data && resultJson.Data.access_token) {
                  response.json({ access_token: resultJson.Data.access_token });
              }
          });
      });

  })
  function GetSignatureUrl(queryString,embedSecret)
  {
    var keyBytes = Buffer.from(embedSecret);
    var hmac = crypto.createHmac('sha256', keyBytes);
    data = hmac.update(queryString);
    gen_hmac= data.digest().toString('base64');
    return gen_hmac;
  }

Filter Syntax:

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 achieve the same RLS for custom columns using Dashboard Parameters. Please refer to this link to create dashboard parameter

Custom Attribute

What is it?

Custom Attributes are name-value pairs saved for users or groups, or sites, dynamically changing data source via queries, expressions, or data source connections to enforce row-level security by tailoring data access to specific users or groups or sites.

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

Pass Custom Attribute via embed_custom_attribute in the token generation method to enforce row-level security by filtering data dynamically based on user or role and pass this token in frontend to render the dashboard.

Node

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.

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

   //Token Generation With Custom Attribute
   app.post('/tokengeneration', function () {

       var serverUrl = "< Bold BI server URL >";
       var siteIdentifier = "< Bold BI server Site Identifier >";
       var dashboardId = "< Dashboard Id >";
       var useremail = "< Bold BI server user Email >";
       var embedSecret = "< Embed Secret key >";
       var customAttribute = "[{\"database_name\":\"DB1\"}]" // Add Custom Attribute Name and Value

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

       //Custom Attribute Query
       queryStringString += "&embed_custom_attribute="+ customAttribute;
       var embedSignature = "&embed_signature=" + GetSignatureUrl(queryString,embedSecret);
       var embedDetailsUrl = "/embed/authorize?" + queryString+embedSignature;

     var serverProtocol = url.parse(serverApiUrl).protocol == 'https:' ? https : http;
     serverProtocol.get(serverApiUrl + embedDetailsUrl, function (resultContent) {
       let str = '';
       resultContent.on('data', function (chunk) {
           str += chunk;
       });
       resultContent.on('end', function () {
               const resultJson = JSON.parse(str);
               if (resultJson && resultJson.ApiStatus && resultJson.Data && resultJson.Data.access_token) {
                   response.json({ access_token: resultJson.Data.access_token });
               }
           });
       });

   })
   function GetSignatureUrl(queryString,embedSecret)
   {
     var keyBytes = Buffer.from(embedSecret);
     var hmac = crypto.createHmac('sha256', keyBytes);
     data = hmac.update(queryString);
     gen_hmac= data.digest().toString('base64');
     return gen_hmac;
   }

Syntax Examples:

Scenario Syntax Example
Single Attribute [{\"Attribute_Name\":\"Value\"}] &embed_custom_attribute=[{\"database_name\":\"DB1\"}]
Multiple Attributes [{\"Attribute_Name1\":\"Value1\",\"Attribute_Name2\":\"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: Restricts data access based on user roles, departments, or tenants.
  • Multi-Tenant Efficiency: Uses a single dashboard template across multiple tenants with different databases.