Skip to main content
Skip table of contents

Secure Shinydocs Search Engine and Dashboards access with OIDC

This guide walks you through securing and configuring access to two components of Shinydocs Pro:

  • Shinydocs Search Engine (powered by OpenSearch) - the backend search and analytics engine that indexes and queries your organization's content.

  • Shinydocs Dashboards (powered by OpenSearch Dashboards) - the web-based interface where users view search results, dashboards, and reports.

Shinydocs Search Engine and Shinydocs Dashboards are branded versions of OpenSearch. OpenSearch is a well respected and document platform, most of this guide comes from the existing documentation from OpenSearch: OpenID Connect - OpenSearch Documentation

By the end of this guide, you will have:

  • Replaced the default demo certificates with certificates issued by your organization.

  • Enabled HTTPS on both the search engine and dashboards.

  • Configured DNS so users can reach the dashboards at a friendly, trusted hostname.

  • Set up single sign-on (SSO) using OpenID Connect with Microsoft Entra ID, so users log in with their existing corporate credentials.

  • Created role-based access controls that determine what each group of users can see and do.

  • Connected the Shinydocs Pro Control Center to the secured services using a dedicated service account.

How Authentication Works in This Setup

Once configured, two separate authentication paths will coexist:

  • Interactive users (people using a browser to access Dashboards) authenticate via OpenID Connect. They click an SSO button, sign in through Microsoft Entra ID, and are redirected back to Dashboards with their identity and roles attached.

  • Backend services (Shinydocs Pro itself, and the internal Dashboards server process) authenticate using a traditional username and password over HTTPS. This is called basic authentication. These service accounts are defined locally inside OpenSearch and never go through Entra ID.

Both paths are active at the same time. The search engine evaluates them in order: if a request includes basic auth credentials, it uses those; if not, it hands off to the OIDC flow. This means enabling SSO does not break Shinydocs Pro's ability to read and write data.

Plan Your Access Model

Before configuring single sign-on, decide which groups of people need access and what they should be allowed to do. This is the most important planning step, and it is much easier to get right before you start editing configuration files.

How Roles Work

The access model has three layers:

  • Entra ID App Roles - defined in your Azure App Registration. These are the labels your identity team assigns to users or groups (e.g., "os_admin", "os_hr_viewer"). They travel inside the authentication token when a user signs in.

  • OpenSearch backend roles - the search engine receives the App Role values from the token and treats them as backend roles.

  • OpenSearch security roles - permission sets that you define in roles.yml and map to backend roles in roles_mapping.yml. This is where you control exactly which indices each group can access and what actions they can perform.

In short: Entra ID roles flow into the token, the token carries them to the search engine, and the search engine maps them to permissions on specific indices.

App Roles vs. Group Claims

Entra ID can send either App Roles (preffered) or Group Claims in the authentication token. For this setup, App Roles are strongly recommended:

  • App Roles appear as clean string values in the token (e.g., "roles": ["os_admin"]). They are simple to map in OpenSearch.

  • Group Claims send Azure group object IDs (long GUIDs). They are harder to work with, and in large organizations with many group memberships, the token can exceed browser cookie size limits, causing login failures.

Important: Organizations where users belong to more than 150 Entra ID groups frequently encounter infinite login redirect loops caused by oversized tokens. App Roles avoid this entirely because only the roles assigned to the specific application are included in the token.

Understanding Index Names and Aliases

When you create a source in the Shinydocs Pro Control Center, the search engine stores its data in an index with a GUID-based name (e.g., a3f8c1d2-7b4e-4f9a-b6c1-8d2e3f4a5b6c). This name is not human-readable, so Shinydocs Pro also creates an alias based on the source name you entered in Shinydocs Pro Control Center.

For example, if you create a source called "Marketing Docs", the alias will be marketing-docs. If you create a source called "HR Policies", the alias will be hr-policies. When defining index-level permissions in OpenSearch roles, you use these aliases (or wildcard patterns that match them) to control access.

Recommended Roles

Most deployments need two categories of roles:

  • Cluster-level roles for administrators and broad-access analysts who need to see everything.

  • Index-scoped roles for teams that should only access specific sources. These are custom roles you define in roles.yml, using index aliases to control which data each team can see.

Important: Every user who accesses Dashboards also needs the opensearch_dashboards_user role. This is a UI-level role that grants access to the Dashboards interface itself. Without it, users authenticate successfully but see a blank page.

The following table shows a recommended starting set. The first three are standard; the index-scoped examples illustrate the pattern you would repeat for each team or source:

App Role

OpenSearch Role

Who Gets It and What They Can Do

os_admin

all_access

IT operations and Shinydocs administrators. Full access to the cluster, all indices, and security configuration. Keep this group very small.

os_analyst

readall

Compliance officers, legal teams, records management. Read-only access across all indices. Cannot modify data or settings.

os_dashboards_user

opensearch_dashboards_user

Everyone who accesses the Dashboards UI. Assign this alongside one of the other roles. Without it, users authenticate but see a blank page.

os_hr_viewer

shinydocs_hr (custom)

Example: HR department. Read access restricted to HR-related source aliases only (e.g., hr-policies, hr-onboarding).

os_legal_viewer

shinydocs_legal (custom)

Example: Legal department. Read access restricted to legal source aliases only (e.g., legal-contracts, legal-memos).

The italicized rows are examples. You would create one App Role and one custom OpenSearch role for each team or group of sources that needs isolated access. The pattern is always the same: define the role in roles.yml with the appropriate index alias patterns, map the App Role to it in roles_mapping.yml, and assign users to the App Role in Entra ID.

Dashboards Tenants (Multi-Tenancy)

In addition to controlling which indices a user can query, you may want to control which saved dashboards, visualizations, and saved searches each team can see. OpenSearch Dashboards supports this through tenants.

A tenant is an isolated workspace inside Dashboards. Saved objects (dashboards, visualizations, index patterns) created in one tenant are not visible in another. Every user has access to a Private tenant (visible only to them) and can be granted access to shared tenants.

There are two common patterns:

Pattern A: Global Tenant + Private Tenants

All users share a Global tenant where organization-wide dashboards are published (e.g., company-wide search, executive summaries). Each user also has their own Private tenant for personal saved searches and experimental visualizations. This is the simplest setup and works well when index-level permissions are the primary access control.

Pattern B: Team-Specific Tenants

Each team gets its own named tenant (e.g., hr-team, legal-team). Dashboards and visualizations created by the HR team are only visible in the HR tenant. This is useful when teams build department-specific dashboards that should not be visible to other teams, or when different teams need different index patterns configured.

To create named tenants, add them to opensearch-security\tenants.yml:

CODE
hr-team:
  reserved: false
  description: "HR department dashboards and saved searches"
 
legal-team:
  reserved: false
  description: "Legal department dashboards and saved searches"

Then grant tenant access in your custom roles. The tenant_permissions block controls which tenants a role can read from or write to.

Note: Tenants control visibility of saved Dashboards objects (dashboards, visualizations, index patterns). They do not control which index data a user can query. Index-level access is controlled by the index_permissions block in the role definition. You typically use both together: index permissions to limit what data a team can search, and tenant permissions to isolate their saved dashboards.

Example: Mapping Entra ID Groups to Roles

A typical enterprise deployment creates Entra ID security groups and assigns them App Roles through the Enterprise Application. Here is an expanded example showing both cluster-level and index-scoped roles:

Entra ID Security Group

Assigned App Roles

Typical Members

SG-Shinydocs-Admins

os_admin, os_dashboards_user

IT operations, Shinydocs admins

SG-Shinydocs-Analysts

os_analyst, os_dashboards_user

Compliance, legal, records mgmt

SG-Shinydocs-HR

os_hr_viewer, os_dashboards_user

HR staff, HR managers

SG-Shinydocs-Legal

os_legal_viewer, os_dashboards_user

Legal team, paralegals

Prerequisites

Before starting, confirm that you have the following:

  • Shinydocs Pro installed and running, with the Search Engine and Dashboards operational (even if currently using HTTP and demo certificates).

  • Access to the server where the Search Engine and Dashboards are installed. The default installation path is C:\ProgramData\Shinydocs\SearchEngine\config for the Search Engine.

  • TLS certificates issued by your organization's certificate authority (CA).

  • Microsoft Entra ID permissions - Global Administrator or Application Administrator in your tenant.

  • A DNS record (or the ability to create one) that points a hostname to your Dashboards server.

  • Network connectivity between the OpenSearch server and login.microsoftonline.com on port 443.

Step 1 - Prepare your TLS Certificates

Shinydocs Pro ships with demo certificates for convenience during initial setup. These are not suitable for production use. Before enabling HTTPS, you need to replace them with certificates issued by your organization's internal certificate authority (CA) or a trusted public CA.

What Ships With Shinydocs Pro

The default config directory (C:\ProgramData\Shinydocs\SearchEngine\config) contains the following certificate files:

CODE
config\
  admin.pem            # Admin client certificate
  admin-key.pem        # Admin client private key
  localhost.pem         # Demo server certificate (CN=localhost)
  localhost-key.pem     # Demo server private key
  root-ca.pem           # Demo root CA certificate
  opensearch.yml
  opensearch-security\  # Security plugin configuration files
  log4j2.properties
  ...

Here is what the directory looks like on a default installation:

image-20260319-140928.png

Default contents of C:\ProgramData\Shinydocs\SearchEngine\config

The demo certificates use CN=localhost and are signed by a demo CA. They will trigger browser warnings and are not trusted by other systems. You need to replace them.

What to Request From Your CA

Contact your organization's certificate team (or whoever manages your internal PKI) and request the following:

Search Engine Certificate (Internal Use)

The search engine is not exposed to end users directly. It is accessed by Shinydocs Pro and by the Dashboards server process, typically over localhost or an internal hostname. However, TLS is still required to encrypt traffic between components.

  • Subject / Common Name (CN): localhost or the internal hostname of the server (e.g., the machine's NetBIOS name or FQDN on the internal network).

  • Subject Alternative Names (SANs): Include localhost, 127.0.0.1, and the server's internal hostname or IP. This ensures connections from Shinydocs Pro (which typically connects via localhost) and from the Dashboards process both validate successfully.

  • Key usage: Server authentication (TLS Web Server Authentication).

  • Format: PEM-encoded. You need two files: the certificate file (.pem) and the private key file (-key.pem).

  • Certificate chain: The certificate file should contain the full chain: the server certificate first, followed by any intermediate CA certificates in order. The root CA certificate should be provided as a separate file.

Dashboards Certificate (User-Facing)

Dashboards is the component that end users access in their browsers, so its certificate must use the DNS hostname you will publish.

  • Subject / Common Name (CN): The hostname users will browse to (e.g., dashboards.corp.example.com).

  • Subject Alternative Names (SANs): Include the DNS hostname and, if the Dashboards and Search Engine are on the same machine, localhost as well.

  • Key usage: Server authentication (TLS Web Server Authentication).

  • Format: PEM-encoded certificate and private key.

  • Certificate chain: Full chain, same as above.

Note: If the Search Engine and Dashboards run on the same server and your CA can issue a single certificate with SANs covering both localhost and the Dashboards DNS hostname, one certificate can be used for both services. Otherwise, request separate certificates.

Admin Certificate (for Security Administration)

  • Subject / CN: A distinguished name that identifies the admin client. The default Shinydocs configuration expects something like CN=os.admin,OU=Shinydocs Pro,O=Shinydocs Corporation,L=Kitchener,ST=Ontario,C=CA. You can use any DN, but it must match the admin_dn value in opensearch.yml.

  • Key usage: Client authentication.

  • Format: PEM-encoded certificate and private key.

Root CA Certificate

  • The root CA certificate (and any intermediates) that signed all of the above. This file is referenced as root-ca.pem in the configuration. If your CA chain has intermediates, bundle them into a single file with the root CA at the bottom.

Replace the Demo Certificates

Once you have your certificates:

  1. Back up the existing demo certificate files in C:\ProgramData\Shinydocs\SearchEngine\config\ to a safe location.

  2. Place your new certificate files in the same config directory, using filenames that make sense for your environment. For example:

    CODE
    config\
      search-engine.pem        # Search engine server certificate (full chain)
      search-engine-key.pem    # Search engine server private key
      admin.pem                # Your admin client certificate
      admin-key.pem            # Your admin client private key
      root-ca.pem              # Your root CA certificate
  3. Place the Dashboards certificate and key in the Dashboards config directory (e.g., dashboards.pem and dashboards-key.pem), along with a copy of root-ca.pem.

Note: You can name the files anything you like, as long as you update the references in opensearch.yml and opensearch_dashboards.yml to match. The examples in this guide use descriptive names for clarity.

Configure DNS

Dashboards is the user-facing component that people access in their browsers. It needs a DNS hostname for two reasons:

  • TLS certificates validate against hostnames. If users browse to an IP address but the certificate's CN/SAN contains a hostname, the browser will show a certificate mismatch error.

  • Entra ID redirect URIs must use a hostname. Microsoft will not accept a bare IP address as a redirect URI for OIDC.

The search engine does not need a public or internal DNS record. It is accessed by Shinydocs Pro and the Dashboards server process over localhost or the machine's internal address, and those connections are covered by the SANs in the search engine certificate.

What to Create

Work with your DNS team to create an A record (or CNAME record, depending on your infrastructure) that points to the server hosting Dashboards:

Record Name

Type

Points To

Purpose

dashboards.corp.example.com

A

10.0.1.50 (your server IP)

Shinydocs Dashboards (port 443)

 Choose a hostname that aligns with your organization's naming conventions. The examples in this guide use dashboards.corp.example.com as a placeholder.

Verify DNS Resolution

Before proceeding, confirm that the record resolves correctly from a client workstation:

CODE
nslookup dashboards.corp.example.com

It should return the expected IP address. If it does not, HTTPS and OIDC configuration will fail later.

Note: If your environment uses split-horizon DNS (different answers for internal vs. external queries), make sure the record resolves correctly from the networks where end users will be browsing from.

Step 2 - Enable HTTPS on the Search Engine

Open C:\ProgramData\Shinydocs\SearchEngine\config\opensearch.yml in a text editor. In its default state, the security plugin is disabled:

CODE
# disable the security plugin on opensearch.
plugins.security.disabled: true

To enable security, comment out (or remove) that line and uncomment the security block below it. Then update the certificate paths and the admin DN to match your new certificates.

Here is the complete security section with the changes highlighted:

YAML
# REMOVE or comment out this line:
# plugins.security.disabled: true
 
# Enable TLS for transport (node-to-node communication)
plugins.security.ssl.transport.pemcert_filepath: search-engine.pem
plugins.security.ssl.transport.pemkey_filepath: search-engine-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
plugins.security.ssl.transport.enforce_hostname_verification: false
 
# Enable TLS for HTTP (API and browser traffic)
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: search-engine.pem
plugins.security.ssl.http.pemkey_filepath: search-engine-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
plugins.security.ssl.http.enabled_protocols:
  - 'TLSv1.2'
  - 'TLSv1.3'
 
# Do NOT use demo certificates in production
plugins.security.allow_unsafe_democertificates: false
 
# Allow the security plugin to initialize its index on first start
plugins.security.allow_default_init_securityindex: true
 
# Admin certificate DN (must match your admin certificate's Subject)
plugins.security.authcz.admin_dn:
  - CN=os.admin,OU=Shinydocs Pro,O=Shinydocs Corporation,L=Kitchener,ST=Ontario,C=CA
 
# Auditing
plugins.security.audit.type: internal_opensearch
plugins.security.audit.config.index: "'security-auditlog-'YYYY-MM"
 
# Snapshot and REST API access
plugins.security.enable_snapshot_restore_privilege: true
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
 
# System indices protection
plugins.security.system_indices.enabled: true
plugins.security.system_indices.indices:
  - ".plugins-ml-*"
  - ".opendistro-*"
  - ".opensearch-*"
  - ".ql-datasources"
  - ".replication-metadata-store"
  - ".opensearch-knn-models"

Important: The admin_dn value must exactly match the Subject (Distinguished Name) of your admin certificate. If you are using a certificate with a different DN, update this value before starting the service. A mismatch will prevent you from running security administration commands.

Note: Certificate file paths in opensearch.yml are relative to the config directory. Since the certificate files sit directly in the config folder, you only need the filename (e.g., search-engine.pem), not a full path.

Restart the Search Engine service after saving. Verify it is running by opening a browser on the server itself and navigating to:

CODE
https://localhost:9200/

You should see a JSON response with the cluster name. If your certificate's SAN includes localhost (as recommended), this should connect without warnings.

Step 3 - Enable HTTPS on Dashboards

Open the Dashboards configuration file (opensearch_dashboards.yml located in C:\ProgramData\Shinydocs\Dashboards\config) and update it with your certificate paths and the HTTPS URL of the search engine. On Windows, use absolute paths with double backslashes.

YAML
# Point Dashboards to the secured search engine (accessed locally)
opensearch.hosts: ["https://localhost:9200"]
opensearch.username: "admin"
opensearch.password: "<admin_password>"
 
# Serve Dashboards on the standard HTTPS port
server.port: 443
 
# Enable HTTPS for the Dashboards web UI
server.ssl.enabled: true
server.ssl.certificate: "C:\\ProgramData\\Shinydocs\\Dashboards\\config\\dashboards.pem"
server.ssl.key: "C:\\ProgramData\\Shinydocs\\Dashboards\\config\\dashboards-key.pem"
 
# Trust the CA that signed the search engine's certificate
opensearch.ssl.certificateAuthorities: ["C:\\ProgramData\\Shinydocs\\Dashboards\\config\\root-ca.pem"]
opensearch.ssl.verificationMode: certificate
 
opensearch.requestHeadersWhitelist: [authorization, securitytenant]
 
opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"]
opensearch_security.readonly_mode.roles: ["kibana_read_only"]
opensearch_security.cookie.secure: true

If the Search Engine and Dashboards are on the same server, the Dashboards config can reference the same root-ca.pem file used by the Search Engine. Adjust the absolute paths accordingly.

A note on port 443: The default Dashboards port is 5601. Changing it to 443 (the standard HTTPS port) is recommended for production because users do not need to remember a port number, firewall rules are simpler, and the URL is cleaner. However, port 443 is a privileged port on some systems and may require the Dashboards service to run with elevated privileges. If your organization uses a reverse proxy (such as IIS Application Request Routing or an F5 load balancer) to terminate TLS in front of Dashboards, you can leave Dashboards on 5601 internally and expose port 443 through the proxy instead.

Restart the Dashboards service. Verify by browsing to:

CODE
https://dashboards.corp.example.com/

You should see the login page served over HTTPS. Since port 443 is the default for HTTPS, it does not need to appear in the URL.

Step 4 - Configure Microsoft Entra ID

Register the Application

  1. Sign into the Azure Portal at https://portal.azure.com .

  2. Navigate to Microsoft Entra ID > App registrations > New registration.

  3. Set the display name (e.g., Shinydocs Pro - Dashboards SSO).

  4. Under Supported account types, select Accounts in this organizational directory only.

  5. Set the Redirect URI to Web and enter:

https://dashboards.corp.example.com/auth/openid/login

  1. Click Register.

Record Key Identifiers

From the App Registration Overview page, copy and save:

  • Application (client) ID - this is your client_id.

  • Directory (tenant) ID - used to construct the OIDC metadata URL:

https://login.microsoftonline.com/<TENANT_ID>/v2.0/.well-known/openid-configuration

Important: Always use your specific Tenant ID in this URL. Do not use the /organizations/ or /common/ variants, as those cause token validation failures.

Create a Client Secret

  1. Go to Certificates & secrets > New client secret.

  2. Enter a description (e.g., Shinydocs Dashboards OIDC) and choose an expiry.

  3. Click Add. Copy the Value immediately - it is only shown once. This is your client_secret.

Create App Roles

  1. Go to App roles > Create app role.

  2. For each role, fill in:

    1. Display name: e.g., os_admin

    2. Allowed member types: Users/Groups

    3. Value: e.g., os_admin (this exact string appears in the token and must match your OpenSearch role mappings)

  3. Click Apply. Repeat for each role. At minimum, create: os_admin, os_analyst, os_dashboards_user, and one role per team that needs index-scoped access (e.g., os_hr_viewer, os_legal_viewer).

Configure API Permissions

  1. Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions.

  2. Add:

    1. openid

    2. email

    3. profile

Assign Users and Groups

  1. Navigate to Enterprise applications (not App registrations) and find the application.

  2. Go to Users and groups > Add user/group.

  3. Select a security group and assign its App Role(s).

  4. Repeat for each group.

Step 5 - Configure the Search Engine for OIDC

Edit C:\ProgramData\Shinydocs\SearchEngine\config\opensearch-security\config.yml. This file defines how the search engine authenticates incoming requests. You need two authentication domains: basic auth for service accounts and OIDC for interactive users.

YAML
_meta:
  type: "config"
  config_version: 2
 
config:
  dynamic:
    authc:
      basic_internal_auth_domain:
        description: "Basic auth for Shinydocs Pro and admin accounts"
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: intern
 
      openid_auth_domain:
        description: "Entra ID SSO for Dashboards users"
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          type: openid
          challenge: false
          config:
            subject_key: preferred_username
            roles_key: roles
            openid_connect_url: https://login.microsoftonline.com/<TENANT_ID>/v2.0/.well-known/openid-configuration
        authentication_backend:
          type: noop

What each setting does:

  • order: 0 on basic auth means it is checked first. If a request carries a username/password header (like requests from Shinydocs Pro), it is authenticated here. Browser requests without credentials fall through to OIDC.

  • challenge: false on the basic domain prevents the browser from showing a username/password popup that would block the SSO redirect.

  • subject_key: preferred_username extracts the user's UPN (e.g., jane.doe@contoso.com) from the token as their OpenSearch identity.

  • roles_key: roles tells OpenSearch to read the App Role values from the roles claim in the JWT.

  • type: noop means the search engine does not look the user up in its internal database after OIDC validation. Everything comes from the token.

Configure Role Mappings

Edit opensearch-security\roles_mapping.yml to connect the Entra ID App Role values to OpenSearch security roles. This file maps backend roles (the App Role values from the token) to OpenSearch security roles (the permission sets you define in roles.yml).

YAML
# --- Cluster-level roles ---
all_access:
  reserved: false
  backend_roles:
    - "os_admin"
  description: "Entra os_admin gets full cluster access"
 
readall:
  reserved: false
  backend_roles:
    - "os_analyst"
  description: "Entra os_analyst gets read-only access to all indices"
 
opensearch_dashboards_user:
  reserved: false
  backend_roles:
    - "os_admin"
    - "os_analyst"
    - "os_dashboards_user"
    - "os_hr_viewer"
    - "os_legal_viewer"
  description: "All SSO users need Dashboards UI access"
 
# --- Index-scoped roles (one per team) ---
 
shinydocs_hr:
  reserved: false
  backend_roles:
    - "os_hr_viewer"
  description: "HR team gets read access to HR source aliases"
 
shinydocs_legal:
  reserved: false
  backend_roles:
    - "os_legal_viewer"
  description: "Legal team gets read access to legal source aliases"

Note: The backend_roles values are case-sensitive and must exactly match the Value field of each App Role in Entra ID. When you add a new team, add their App Role value to the opensearch_dashboards_user mapping as well, or they will not be able to use the Dashboards UI.

Define Custom Roles in roles.yml

Add index-scoped roles to opensearch-security\roles.yml. Each custom role specifies which index aliases the team can access and what actions they can perform. Use the alias names from your Shinydocs Pro Control Center sources.

Example: HR viewer role

This role grants read-only access to all sources whose aliases start with hr- (e.g., hr-policies, hr-onboarding, hr-employee-docs):

YAML
shinydocs_hr:
  cluster_permissions:
    - "cluster_composite_ops_ro"
  index_permissions:
    - index_patterns:
        - "hr-*"
      allowed_actions:
        - "read"
        - "search"
  tenant_permissions:
    - tenant_patterns:
        - "hr-team"
      allowed_actions:
        - "kibana_all_write"

Example: Legal viewer role

Same pattern, scoped to legal source aliases:

CODE
shinydocs_legal:
  cluster_permissions:
    - "cluster_composite_ops_ro"
  index_permissions:
    - index_patterns:
        - "legal-*"
      allowed_actions:
        - "read"
        - "search"
  tenant_permissions:
    - tenant_patterns:
        - "legal-team"
      allowed_actions:
        - "kibana_all_write"

How to adapt this pattern for your environment:

  • Look at the source names in your Shinydocs Pro Control Center. If HR has sources named "HR Policies" and "HR Onboarding", their aliases will be hr-policies and hr-onboarding. A pattern of hr-* covers both.

  • If a team's sources do not share a common prefix, you can list multiple specific aliases instead of a wildcard:

    • CODE
        index_permissions:
          - index_patterns:
              - "employee-handbook"
              - "benefits-guide"
              - "training-materials"
            allowed_actions:
              - "read"
              - "search"
    • The tenant_permissions block is optional. Include it if you are using team-specific tenants. The kibana_all_write action allows users to create and edit saved dashboards and visualizations within that tenant.

    • If you are using the Global + Private tenant pattern instead, omit the tenant_permissions block entirely. Users will work in the Global tenant (for shared dashboards) and their Private tenant (for personal/team work).

Important: Index patterns in roles.yml match against both index names and aliases. Since Shinydocs Pro uses GUID-based index names with human-readable aliases, always use the alias names in your patterns. If you use the raw GUID index name, a reindex operation could change it and break your role.

Step 5.1 - Configure Tenants (if you are using them in your model)

If you are using team-specific tenants, add them to opensearch-security\tenants.yml:

CODE
hr-team:
  reserved: false
  description: "HR department workspace"
 
legal-team:
  reserved: false
  description: "Legal department workspace"

If you are using only the Global and Private tenants (Pattern A), you do not need to modify tenants.yml.

Change the Default Admin Password

Before applying the security configuration, you must change the default password for the admin internal user. The default password ships with every Shinydocs Pro installation and is publicly known.

  1. Open a command prompt and navigate to the security plugin's tools directory:

    CODE
    cd C:\ProgramData\Shinydocs\SearchEngine\plugins\opensearch-security\tools
    1. Run the password hashing tool to generate a bcrypt hash of your new password:

      CODE
      hash.bat
    2. When prompted, enter your new password. The tool will output a bcrypt hash string that looks something like:
      $2y$12$88IFVl6IfIwCFh5aQYfOmuXVL9j2hz/GusQb35o.4sdTDAEMTOD.K

    3. Copy the hash. Open C:\ProgramData\Shinydocs\SearchEngine\config\opensearch-security\internal_users.yml and replace the existing hash for the admin user:

      CODE
      admin:
        hash: "$2y$12$<your-new-hash-here>"
        reserved: true
        backend_roles:
          - "admin"
        description: "Admin user"
    4. If you plan to create a dedicated service account for Shinydocs Pro (recommended), add it to the same file:

      CODE
      shinydocs-service:
        hash: "$2y$12$<hash-of-service-account-password>"
        reserved: false
        backend_roles:
          - "admin"
        description: "Service account for Shinydocs Pro"

Apply the Security Configuration

You must run this. Failure to do this step will result in an incomplete configuration. This must also be run when you change the built-in admin password.

Run the security admin tool to push the updated YAML files into the cluster. On Windows:

CMD

OR

PowerShell

CODE
cd C:\ProgramData\Shinydocs\SearchEngine
 
plugins\opensearch-security\tools\securityadmin.bat ^
  -cd config\opensearch-security\ ^
  -icl -nhnv ^
  -cacert config\root-ca.pem ^
  -cert config\admin.pem ^
  -key config\admin-key.pem

CODE
cd C:\ProgramData\Shinydocs\SearchEngine

plugins\opensearch-security\tools\securityadmin.bat `
  -cd config\opensearch-security\ `
  -icl -nhnv `
  -cacert config\root-ca.pem `
  -cert config\admin.pem `
  -key config\admin-key.pem

Important: This command replaces the entire security configuration in the cluster. Make sure you are applying a complete set of files (config.yml, roles.yml, roles_mapping.yml, internal_users.yml, action_groups.yml, tenants.yml). Missing files will reset those sections to defaults.

securityadmin.bat pushes changes automatically and immediately, a restart of Shinydocs Search Engine is NOT required.

Step 6 - Configure Dashboards for OIDC

Add the following OIDC settings to opensearch_dashboards.yml, below the HTTPS settings you configured previously:

CODE
# Enable both SSO and basic auth on the login page
opensearch_security.auth.multiple_auth_enabled: true
opensearch_security.auth.type: ["openid", "basicauth"]
 
# OIDC provider settings (from your Entra ID App Registration)
opensearch_security.openid.connect_url: "https://login.microsoftonline.com/<TENANT_ID>/v2.0/.well-known/openid-configuration"
opensearch_security.openid.client_id: "<APPLICATION_CLIENT_ID>"
opensearch_security.openid.client_secret: "<CLIENT_SECRET>"
opensearch_security.openid.base_redirect_url: "https://dashboards.corp.example.com"
opensearch_security.openid.scope: "openid profile email"
 
# Cookie handling for large Entra ID tokens
opensearch_security.openid.extra_storage.cookie_prefix: security_authentication_oidc
opensearch_security.openid.extra_storage.additional_cookies: 5

Key settings:

  • multiple_auth_enabled: true shows both an SSO button and a username/password form on the login page.

  • base_redirect_url must exactly match the Redirect URI configured in Entra ID (including https, hostname, and port).

  • additional_cookies: 5 accommodates larger Entra ID tokens. Increase this if users experience login failures.

Restart the Dashboards service after saving.

Step 7 - Verify Everything Works

Test SSO Login

  1. Open https://dashboards.corp.example.com in a browser.

  2. You should see a login page with both a username/password form and an OpenID Connect login button.

  3. Click the OIDC button. You should be redirected to the Microsoft Entra ID sign-in page.

  4. Sign in with an account that has been assigned an App Role.

  5. After authentication, Dashboards should load. Check your identity and roles under the Security menu.

Verify Role Mapping

Once logged in via SSO, confirm:

  • Username matches the user's UPN (e.g., jane.doe@contoso.com).

  • Backend roles lists the App Role values assigned to that user (e.g., os_analyst).

  • Mapped roles shows the corresponding OpenSearch roles (e.g., readall, opensearch_dashboards_user).

Test Basic Auth

On the same login page, use the username/password form to sign in as the admin internal user. This confirms that basic auth still works, which is essential for Shinydocs Pro's backend connection and for emergency access if Entra ID is unavailable.

Step 8 - Connect Shinydocs Pro to the Secured Services

Shinydocs Pro communicates with the search engine and dashboards as a backend service. It uses basic authentication (username and password) over HTTPS. It does not use OIDC. This is the intended design: the Pro application reads and writes index data programmatically, so it authenticates with a service account, not an interactive user.

After enabling HTTPS, you need to update the Shinydocs Pro Control Center to use the new HTTPS URLs and credentials.

Update Service URLs and Credentials

image-20260319-152533.png
  1. Open the Shinydocs Pro Control Center in your browser.

  2. Navigate to Settings > Services.

  3. Under Search engine:

    1. Change the URL from http://localhost:9200/ to https://localhost:9200/. Since Shinydocs Pro connects to the search engine locally, localhost is the correct hostname here.

    2. Enter the Username and Password for the internal service account (e.g., admin or a dedicated account you created in internal_users.yml).

    3. If your certificates are signed by an internal CA that is not in the server's trusted root store, check Allow invalidated certificates. For certificates from a trusted CA, leave this unchecked.

  4. Under Search dashboards:

    1. Change the URL to https://dashboards.corp.example.com/.

    2. Enter the same (or a separate) service account credentials.

    3. Configure the certificate checkbox as above.

  5. Save the settings.

Best Practices for the Service Account

  • Use a dedicated service account rather than the default admin user. Create a new internal user in internal_users.yml with a strong, randomly generated password and only the permissions Shinydocs Pro needs.

  • Rotate the password according to your organization's credential policy. When you rotate, update both internal_users.yml (then re-run securityadmin) and the Shinydocs Pro Control Center settings.

  • Do not use OIDC credentials for the Shinydocs Pro service connection. The Pro application is a backend service and must use basic auth.


Troubleshooting

This section covers common issues you may encounter while securing the Shinydocs Search Engine, Dashboards, and OIDC single sign-on. Issues are grouped by the stage of the setup where they typically appear.

General Diagnostic Steps

Before diving into specific symptoms, gather the following information. This will help you (or Shinydocs Support) resolve problems faster.

Enable Debug Logging for the Security Plugin

Add the following lines to the Search Engine's log4j2.properties file (located in the config directory alongside opensearch.yml), then restart the Shinydocs Search Engine service:

logger.securityjwt.name = com.amazon.dlic.auth.http.jwt

logger.securityjwt.level = trace

This produces detailed output in the Search Engine logs showing exactly how each incoming request is authenticated, which claims are extracted from tokens, and why authentication may be failing. Disable trace logging after troubleshooting, as it generates a large volume of log data.

Where to Find Logs

  • Search Engine logs: C:\ProgramData\Shinydocs\SearchEngine\logs\

  • Dashboards logs: Check the Dashboards service console output or the logs directory in your Dashboards installation folder.

  • Control Center logs: Available in Settings > Logs within the Control Center UI, or download them using the download button for a support ticket.

  • Windows Event Viewer: Check the Application and System logs for service start/stop failures.

Decode the Entra ID Token

If SSO login completes but role mapping or identity is wrong, decode the token to inspect its claims. After signing in via OIDC, capture the token from browser developer tools (Network tab, look for the callback request) and paste it into https://jwt.ms to view the claims. Confirm that the "roles" claim contains the expected App Role values and that the "preferred_username" claim matches the expected user identity.

TLS and Certificate Issues

These issues typically appear during Step 1 (Prepare TLS Certificates) and Step 2 (Enable HTTPS on the Search Engine).

Symptom

Likely Cause

Resolution

Search Engine service fails to start after enabling security.

Certificate files are missing, the file paths in opensearch.yml are incorrect, or the PEM files are malformed.

Verify that every certificate file referenced in opensearch.yml exists in the config directory. Open each .pem file in a text editor and confirm it begins with -----BEGIN CERTIFICATE----- or -----BEGIN PRIVATE KEY-----. Check the Search Engine logs for specific SSL initialization errors.

Browser shows "Your connection is not private" or a certificate warning when accessing Dashboards.

The root CA that signed the Dashboards certificate is not trusted by the client machine's certificate store.

Install root-ca.pem in the Trusted Root Certification Authorities store on client machines. In enterprise environments, deploy it via Group Policy. If using an internal CA, this is expected behavior until the CA is trusted.

securityadmin.bat fails with an SSL handshake error.

The admin_dn value in opensearch.yml does not match the Subject (Distinguished Name) of the admin certificate, or the wrong certificate files are being passed to securityadmin.

Run the following to inspect the admin certificate's Subject:

openssl x509 -in admin.pem -noout -subject

Compare the output to the plugins.security.authcz.admin_dn value in opensearch.yml. They must match exactly, including spaces and the order of fields. Also confirm you are passing the correct -cert, -key, and -cacert files to securityadmin.bat.

securityadmin.bat reports "ERR: An unexpected SSLHandshakeException" or "unable to find valid certification path."

The root-ca.pem passed to securityadmin does not match the CA that signed the Search Engine's certificate.

Verify that root-ca.pem is the same CA (or CA chain) that signed search-engine.pem. If your CA has intermediate certificates, bundle them into root-ca.pem with the root CA at the bottom.

Dashboards cannot connect to the Search Engine after enabling HTTPS. The Dashboards UI shows a blank page or a connection error.

The opensearch_dashboards.yml file still points to http://localhost:9200 instead of https://localhost:9200, or the CA certificate path for the Search Engine is wrong.

In opensearch_dashboards.yml, confirm that opensearch.hosts uses https://localhost:9200. Verify that opensearch.ssl.certificateAuthorities points to a valid copy of root-ca.pem and that opensearch.ssl.verificationMode is set to "certificate".

OIDC and Single Sign-On Issues

These issues relate to Steps 4 through 7 (Entra ID configuration, Search Engine OIDC config, Dashboards OIDC config, and verification).

Symptom

Likely Cause

Resolution

Infinite redirect loop after signing in through Entra ID. The browser cycles between Dashboards and the Entra ID login page without ever loading.

The Entra ID token is too large to fit in the browser's cookies. This commonly happens when using Group Claims instead of App Roles, or when a user belongs to a large number of groups (150+).

Switch from Group Claims to App Roles as described in the "App Roles vs. Group Claims" section of this guide. If you are already using App Roles, increase the additional_cookies value in opensearch_dashboards.yml:

opensearch_security.openid.extra_storage.additional_cookies: 10

Also increase the HTTP header size limit in opensearch.yml:

http.max_header_size: 16384

Restart both services after making changes.

"No subject found in JWT token" appears in the Search Engine logs.

The subject_key setting in config.yml does not match a claim that exists in the Entra ID token.

Decode the token at https://jwt.ms and look for the claim that contains the user's identity. For Entra ID v2.0 tokens, "preferred_username" is typical. Other possibilities include "email" or "sub". Update subject_key in the openid_auth_domain section of config.yml to match the claim name, then re-run securityadmin.bat.

Roles not appearing after login. The user authenticates successfully via SSO but has no backend roles or mapped roles.

The roles_key setting does not match the claim in the token, or the user has not been assigned an App Role in the Enterprise Application.

Decode the token and verify the "roles" claim is present and contains the expected App Role values (e.g., "os_admin"). If the claim is missing, check the Enterprise Application in Entra ID and confirm the user or their group is assigned to the correct App Roles. If the claim exists but uses a different name, update roles_key in config.yml and re-run securityadmin.bat.

AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application.

The base_redirect_url in opensearch_dashboards.yml does not match the Redirect URI configured in the Entra ID App Registration.

The full redirect URI is the base_redirect_url value plus /auth/openid/login. Confirm that both match exactly, including the protocol (https), hostname, port (if non-standard), and path. A common mistake is a trailing slash mismatch. Update either the Entra ID App Registration or opensearch_dashboards.yml so they are identical.

AADSTS700016: Application not found in the directory. This can happen if the application has not been installed by the administrator of the tenant.

The client_id in opensearch_dashboards.yml is incorrect, or the OIDC metadata URL uses the wrong tenant ID.

Verify that opensearch_security.openid.client_id matches the Application (client) ID from the App Registration overview page. Also verify that the Tenant ID in the connect_url is correct. Do not use /organizations/ or /common/ in the metadata URL; always use your specific Tenant ID.

Login page shows only a username/password form with no OIDC button.

The OIDC authentication type is not configured in opensearch_dashboards.yml, or the multiple auth setting is missing.

Confirm both settings are present:

opensearch_security.auth.multiple_auth_enabled: true

opensearch_security.auth.type: ["openid", "basicauth"]

Restart the Dashboards service after adding them.

Clock skew errors in the Search Engine logs. Messages referencing "nbf" or "exp" claims indicate the token is being rejected as not yet valid or already expired.

The system clock on the Shinydocs Pro server is out of sync with the Entra ID authentication servers.

Synchronize the server's clock using NTP (e.g., w32tm /resync on Windows). If a small skew is unavoidable, add a tolerance setting to the OIDC auth domain in config.yml:

jwt_clock_skew_tolerance_seconds: 60

Then re-run securityadmin.bat.

Role Mapping and Access Issues

These issues appear after OIDC is working but users cannot see the expected data or UI elements.

Symptom

Likely Cause

Resolution

User authenticates via SSO but sees a blank Dashboards page with no content.

The user's App Roles do not include a mapping to the opensearch_dashboards_user role. This role is required for Dashboards UI access.

Edit roles_mapping.yml and add the user's App Role value to the opensearch_dashboards_user backend_roles list. Re-run securityadmin.bat. Every user who accesses the Dashboards UI needs this role in addition to their data-access role.

User can log in and see the Dashboards UI but cannot see any data when searching or viewing dashboards.

The user's mapped OpenSearch role does not grant access to the indices (aliases) that contain the data, or the index alias patterns in roles.yml are incorrect.

Check the user's mapped roles in the Dashboards Security menu. Then review the corresponding role definition in roles.yml. Verify that the index_patterns match the aliases used by your Shinydocs Pro sources. You can find the alias names in the Control Center Sources page; they are lowercase, hyphenated versions of the source names you entered.

User can see some sources but not others, even though they should have access to all of them.

The index alias patterns in the custom role are too narrow. For example, the pattern "hr-*" will not match a source aliased as "human-resources-policies".

Review the source names in Control Center and the corresponding aliases. Adjust the index_patterns in roles.yml to match. You can use multiple patterns in a single role, or use broader wildcards. After editing, re-run securityadmin.bat.

Dashboards visualizations and saved objects from one team are visible to another team.

All users are working in the Global tenant, which shares all saved objects. Team-specific tenants have not been configured.

If you need isolated workspaces, create named tenants in tenants.yml (see "Dashboards Tenants" in the Plan Your Access Model section) and add tenant_permissions to each team's role in roles.yml. Re-run securityadmin.bat.

Changes to roles.yml or roles_mapping.yml do not seem to take effect.

The security configuration was edited on disk but securityadmin.bat was not re-run to push the changes into the cluster.

OpenSearch stores its active security configuration in an internal index, not on disk. Editing the YAML files alone does nothing until you run securityadmin.bat to load them. After running securityadmin, you do not need to restart the Search Engine service; the changes take effect immediately.

Shinydocs Pro Control Center Connection Issues

These issues appear when connecting the Shinydocs Pro Control Center to the secured Search Engine and Dashboards (Step 8).

Symptom

Likely Cause

Resolution

Shinydocs Pro cannot connect to the Search Engine after enabling HTTPS. Sources fail to run and the Control Center shows connection errors.

The Service URL in Control Center still uses http:// instead of https://, or the credentials are wrong.

In Control Center, navigate to Settings > Services > Search engine. Change the URL from http://localhost:9200/ to https://localhost:9200/. Enter the correct username and password for the internal service account. If your certificates are signed by an internal CA, check the "Allow invalidated certificates" option.

Shinydocs Pro connects, but source analysis jobs fail with authentication errors.

The admin password was changed (as required in the guide) but the Control Center was not updated with the new password.

Update the password in Settings > Services for both the Search engine and Search dashboards entries. The credentials here must match the internal_users.yml entries. Remember that Shinydocs Pro uses basic authentication, not OIDC.

Control Center shows a certificate validation error when connecting to Dashboards.

The Dashboards certificate is signed by an internal CA that is not in the server's trusted root store, and "Allow invalidated certificates" is not checked.

Either install the root CA certificate in the Windows Trusted Root Certification Authorities store on the Shinydocs Pro server, or check the "Allow invalidated certificates" option in Settings > Services > Search dashboards.

DNS Issues

Symptom

Likely Cause

Resolution

DNS name does not resolve when running nslookup from a client workstation.

The DNS record has not been created, has not propagated, or the client is using a DNS server that does not have the record.

Confirm the A or CNAME record exists with your DNS team. If using Active Directory-integrated DNS, allow time for replication. Run nslookup from the server itself to confirm local resolution. If your environment uses split-horizon DNS, verify the record resolves correctly from the network where end users will browse.

DNS resolves but the browser shows a certificate mismatch error (e.g., "NET::ERR_CERT_COMMON_NAME_INVALID").

The hostname users are browsing to does not match the CN or any SAN in the Dashboards certificate.

Inspect the Dashboards certificate to see what names it covers:

openssl x509 -in dashboards.pem -noout -text | findstr /C:"Subject:" /C:"DNS:"

If the hostname is missing, request a new certificate from your CA with the correct SAN entries.

Still Stuck?

If you have worked through the relevant sections above and the issue persists:

  1. Collect the Search Engine logs (with trace-level security logging enabled), Dashboards logs, and Control Center logs.

  2. If the issue involves OIDC, capture a decoded copy of the Entra ID token (redact any sensitive values).

  3. Submit a support ticket at https://shinydocs.atlassian.net/servicedesk/customer/portal/1 with the above information attached.

For issues specific to OpenSearch security configuration (not related to Shinydocs Pro itself), the OpenSearch documentation provides additional troubleshooting guidance at https://docs.opensearch.org/latest/troubleshoot/openid-connect/ .

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.