Setup SeekTable for secure embedding

You can embed SeekTable reports into your web application in a secure way by enabling JWT-based authentication for published reports or read-only app view. Secure embedding is available only for self-hosted SeekTable (or managed instance) and only for user accounts with Advanced Publishing subscription. How it works:

Your web app
Generates secure JSON Web Token
Secure report link
JWT is passed to SeekTable report as an URL parameter or cookie
SeekTable
Decodes/verifies JWT and applies claims as report parameters.

JWT lifetime can be is limited by its expiration date. JWT claims (payload) may be contain report parameters and in this way you can organize row-level security for embedded reports (without SSO): each 'main' app user may have its own set of parameters that restrict access to the data. Users cannot change these parameters because their JWT tokens are signed with a secret key. JWT tokens may be encrypted with symmetric algorithm, and in this case even values of parameters passed in JWT are secured (cannot be accessed by end-users).

If you want to evaluate this feature before purchase you can request free 14-day trial.
How to enable JWT-based auth for embedded SeekTable views:

Step 1: Configure SeekTable JWT validation for published reports

Find docker-compose.seektable.env file and add the following lines:

SeekTable_ST__PublicReport__AuthJwtUrlParameter=auth
SeekTable_ST__PublicReport__AuthJwtCookieName=cookie_name_or_empty_if_not_used
SeekTable_ST__PublicReport__AuthJwt__ValidIssuer=your_web_app_issuer_value
SeekTable_ST__PublicReport__AuthJwt__ValidateIssuer=true
SeekTable_ST__PublicReport__AuthJwt__ValidateAudience=false
SeekTable_ST__PublicReport__AuthJwt__ValidateLifetime=true
SeekTable_ST__PublicReport__AuthJwt__ValidateIssuerSigningKey=true
SeekTable_ST__PublicReport__AuthJwt__IssuerSigningKeyString=your_secret_signing_key_min_16_chars

If you want to use encrypted JWT also add:

SeekTable_ST__PublicReport__AuthJwt__TokenDecryptionKeyString=your_secret_decryption_key_min_16_chars

Then re-create seektable/seektable docker container (this is performed automatically if you use docker compose up to start the containers).
Now you should see Security tab on "Configure Published Report" form:

Configure Published Report: Security tab

Step 2: Generate JWT in your web application

The following code snippets illustrate how to generate JSON Web Token for embeds:

// nuget package: System.IdentityModel.Tokens.Jwt
var handler = new JwtSecurityTokenHandler();  
var signingCredentials = new SigningCredentials(
  new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("your_secret_signing_key_min_16_chars")),
  SecurityAlgorithms.HmacSha256Signature);
var token = handler.CreateJwtSecurityToken(
  subject: new ClaimsIdentity(new[] { new Claim("report_param_name", "report_param_val") }),
  signingCredentials: signingCredentials,
  audience: "",
  issuer: "your_web_app_issuer_value",
  expires: DateTime.UtcNow.AddMinutes(5)); // 5 mins expiration
var jwt = handler.WriteToken(token);
// nuget package: System.IdentityModel.Tokens.Jwt
var handler = new JwtSecurityTokenHandler();
var signingCredentials = new SigningCredentials(
  new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("your_secret_signing_key_min_16_chars")),
  SecurityAlgorithms.HmacSha256Signature);
var encryptCredentials = new EncryptingCredentials(
  new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("your_secret_decryption_key_min_16_chars")),
  SecurityAlgorithms.Aes128KW,
  SecurityAlgorithms.Aes128CbcHmacSha256);
var tokenDescriptor = new SecurityTokenDescriptor {
  Audience = "",
  Issuer = "your_web_app_issuer_value",
  Subject = new ClaimsIdentity(new[] { new Claim("report_param_name", "report_param_val") }),
  Expires = DateTime.UtcNow.AddMinutes(5), // 5 mins expiration
  EncryptingCredentials = encryptCredentials,
  SigningCredentials = signingCredentials
};
var encryptedJwt = handler.CreateEncodedJwt(tokenDescriptor);
// module: jsonwebtoken
var jwt = require("jsonwebtoken");
var expiresInMins = 5;
var payload = {
  report_param_name: "report_param_value",
  iss: "your_web_app_issuer_value",
  exp: Math.round(Date.now() / 1000) + (expiresInMins * 60)
};
var token = jwt.sign(payload, "your_secret_signing_key_min_16_chars");
# package: PyJWT
import jwt
import time
payload = {
  "report_param_name": "report_param_value",
  "iss": "your_web_app_issuer_value",
  "exp": round(time.time()) + (60 * 5) # 5 mins expiration
}
token = jwt.encode(payload, "your_secret_signing_key_min_16_chars", algorithm="HS256")
require_once "./vendor/firebase-php-jwt/JWT.php";
use \Firebase\JWT\JWT;

$jwtSigningKeyStr = "your_secret_signing_key_min_16_chars";
$jwtIssuer = "your_web_app_issuer_value";
$payload = [
  "report_param_name" => "report_param_value",			
  "iss" => $jwtIssuer,
  "exp" => strtotime("+5 minutes")
];
$token = JWT::encode($payload, $jwtSigningKeyStr);

On SeekTable side JWT payload claim values are mapped to System.Security.Claims.Claim objects where Value is always converted to a string. As a result, it is not possible to provide multiple values simply by specifying a JSON array as a claim value. To overcome this limitation the following workaround may be used:

  • in the JWT payload (that is composed in your app) pass multiple values as a comma or semicolon (or any other separator) string, something like value,value2,value3
  • in the cube configuration configure an Expression for the multi-value parameter that comes from JWT (let's assume that multi-value parameter's Name is 'param_name'):
    Parameter["param_name"]!=null && Parameter["param_name"].Length==1 && Parameter["param_name"][0].ToString().Contains(",") ? String.Split(",", Parameter["param_name"][0]) : Parameter["param_name"]
    The idea is to split a single string value if it contains a separator.

If you don't use C#/.NET please check your development platform about how to generate JSON Web Token. Notes:

Step 3: Pass JWT to embedded SeekTable report

There are 2 ways how you can pass generated JWT to the report embedded with IFRAME:

Important notes:

Embedded app view

If you want to offer to users of your app a higher level of reports interactivity and allow them to make ad-hoc queries you can embed SeekTable's "app" view (read-only access to some user account) - to get the point just imagine that whole demo.seektable.com view is embedded (without top-menu):

Embedded SeekTable app view (report builder) for ad-hoc queries

Technically this works in this way:

If you have any questions about SeekTable embedded capabilities don't hesitate to contact us.