> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect OpenSearch with JWT Bearer Token – StackOne Hub

> Link a OpenSearch account in the StackOne Hub using JWT Bearer Token. End-user guide to authorize the integration and start using OpenSearch actions.

<Warning>JWT authentication requires a cluster admin to enable the Security Plugin's `jwt_auth_domain` before this connector can use it. The cluster must also serve a TLS certificate signed by a Certificate Authority (public or internal) that the calling environment trusts.</Warning>

<section data-guide-section data-guide-scopes="">
  <h2>Enable JWT authentication on the OpenSearch cluster</h2>

  <p>A cluster administrator configures the OpenSearch Security plugin to accept JWTs by adding a `jwt_auth_domain` block to `config/opensearch-security/config.yml` and applying it with `securityadmin.sh`. This step is one-time — end users creating connections can skip it if the admin has already enabled JWT.</p>

  <Steps>
    <Step title="Add the jwt_auth_domain block to config.yml">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>Sample block using an HMAC shared secret. For RSA or ECDSA, set `signing_key` to the (non-Base64-encoded) public key wrapped in `-----BEGIN PUBLIC KEY-----` / `-----END PUBLIC KEY-----` — the plugin auto-detects the algorithm. For a rotating IdP, use `jwks_uri` in place of `signing_key`.</p>

        <ul>
          <li>\`\``yaml
                    jwt_auth_domain:
                      http_enabled: true
                      transport_enabled: true
                      order: 0
                      http_authenticator:
                        type: jwt
                        challenge: false
                        config:
                          signing_key: "<base64-encoded HMAC secret>"
                          jwt_header: "Authorization"
                          jwt_url_parameter: null
                          subject_key: null
                          roles_key: null
                          required_audience: null
                          required_issuer: null
                          jwt_clock_skew_tolerance_seconds: 20
                      authentication_backend:
                        type: noop
                    `\`\`</li>
          <li>Apply the config with `plugins/opensearch-security/tools/securityadmin.sh` and reload.</li>
          <li>Because JWTs are self-contained, `authentication_backend` is set to `noop`.</li>
          <li>Full reference: <a href="https://docs.opensearch.org/latest/security/authentication-backends/jwt/" target="_blank" rel="noopener noreferrer">JSON Web Token authentication</a>.</li>
        </ul>
      </div>
    </Step>

    <Step title="Configure the claim-to-role mapping">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>Once JWT auth accepts the token, the user still needs mapped OpenSearch roles.</p>

        <ul>
          <li>The subject claim (`sub` by default) becomes the OpenSearch username. Override with `subject_key` if your IdP puts the username elsewhere.</li>
          <li>The `roles_key` config value points at the claim carrying the user's role list. Set it (e.g. `roles_key: "roles"`) if you want the JWT to carry OpenSearch role membership.</li>
          <li>Alternatively, map the subject or a backend role via Dashboards: <strong>Security</strong> > <strong>Roles</strong> > select role > <strong>Mapped users</strong> > <strong>Manage mapping</strong> > <strong>Map</strong>.</li>
        </ul>
      </div>
    </Step>
  </Steps>
</section>

<section data-guide-section data-guide-scopes="">
  <h2>Generate a signed JWT from your identity provider</h2>

  <p>Sign in to your IdP (Okta, Azure AD, Auth0, or a custom signing service) and mint a JWT for the integration user. The token must be signed with the same key material the cluster is configured to verify.</p>

  <Steps>
    <Step title="Add the required claims to the token">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>The cluster validates these claims automatically:</p>

        <ul>
          <li>Include a `sub` claim (or the `subject_key` claim your admin configured) whose value the cluster's role-mapping recognises.</li>
          <li>Include an `exp` (expiration) claim reasonable for the workload. Long-lived tokens are simpler; short-lived tokens are safer — the cluster tolerates up to `jwt_clock_skew_tolerance_seconds` (default 30 seconds) of clock drift.</li>
          <li>If `required_audience` or `required_issuer` are set on the cluster, the token must include matching `aud` / `iss` claims — otherwise the request is rejected as unauthorised.</li>
          <li>Supported algorithms: HS256/384/512 (HMAC), RS256/384/512 (RSA), PS256/384/512 (RSA-PSS), ES256/384/512 (ECDSA).</li>
          <li>Short-lived tokens must be refreshed externally before expiry — the connector does not refresh them automatically. When your token nears `exp`, generate a new one and update the connection.</li>
        </ul>
      </div>
    </Step>
  </Steps>
</section>

<section data-guide-section data-guide-scopes="">
  <h2>Copy the endpoint URL</h2>

  <p>Enter the fully-qualified HTTPS URL of your cluster's REST API.</p>

  <Steps>
    <Step title="Copy the URL from your platform">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>The URL depends on your deployment.</p>

        <ul>
          <li>For <strong>self-hosted</strong> clusters, an HTTPS URL to the cluster's REST port (default `9200`).</li>
          <li>For <strong>hosted providers with JWT support</strong>, the endpoint URL is shown in the provider's console.</li>
          <li>The URL must use HTTPS — the Security Plugin requires TLS.</li>
          <li>No trailing slash.</li>
        </ul>
      </div>
    </Step>
  </Steps>
</section>

<section data-guide-section data-guide-scopes="">
  <h2>Verify the credentials</h2>

  <p>Verify the token round-trips through the cluster before configuring the connector.</p>

  <Steps>
    <Step title="Verify with a manual health check">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>From a shell that can reach the cluster, send `GET /_cluster/health` with the `Authorization: Bearer <jwt>` header and inspect the response:</p>

        <ul>
          <li><strong>200 OK</strong> with a JSON status — the token is accepted.</li>
          <li><strong>401 Unauthorized</strong> — the JWT signature or claims don't validate. Check that the `signing_key` on the cluster matches the IdP's signing key, that `required_audience` / `required_issuer` (if set) match the token, and that `exp` has not passed.</li>
          <li><strong>403 Forbidden</strong> — the JWT authenticates but the subject / roles claim is not mapped to a role with the required permissions. Update role mapping in Dashboards or the `roles_key` claim in the token.</li>
        </ul>
      </div>
    </Step>
  </Steps>
</section>

<section data-guide-section data-guide-scopes="">
  <h2>Enter credentials in StackOne Hub</h2>

  <p>Paste the values below into StackOne Hub to connect the account.</p>

  <Steps>
    <Step title="Fill in the connection fields">
      <div data-guide-step data-guide-scopes="" data-guide-display-scopes-list="">
        <p>Copy each value from the JWT and the cluster endpoint.</p>

        <ul>
          <li><strong>OpenSearch Endpoint URL</strong> — the HTTPS endpoint from step 3.</li>
          <li><strong>JWT Bearer Token</strong> — paste the JWT exactly as issued (three base64url segments separated by dots). Do not add the `Bearer` prefix — StackOne adds it automatically.</li>
          <li><strong>OpenSearch Dashboards URL</strong> — optional. Required only for `dashboards_*` actions. Leave blank for core datasync workflows.</li>
        </ul>
      </div>
    </Step>
  </Steps>
</section>

<div data-whitelabel-hide>
  <h2>Linking the Account from the Hub</h2>

  <Steps>
    <Step title="Navigate to the Hub">
      Use one of the three <a href="/connect/managing-connectors/linking-accounts">Linking Account Methods</a> to access the Hub.
    </Step>

    <Step title="Fill out the fields">
      Fill out the following fields using details from your provider:

      <ul>
        <li><strong>OpenSearch Endpoint URL</strong></li>
        <li><strong>JWT Bearer Token</strong></li>
        <li><strong>OpenSearch Dashboards URL</strong> (Optional)</li>
      </ul>
    </Step>

    <Step title="Connect">
      <ul>
        <li>Click <strong>Connect</strong></li>
        <li>If applicable, the provider will redirect you to a sign-in or authorization page. Complete the provider's authorization flow.</li>
        <li>Once authorization is successful, you will see a confirmation popup</li>
      </ul>
    </Step>
  </Steps>

  <p>If the account linking is successful, you will see the newly linked account in your <a href="/gateway/concepts/linked-accounts">Accounts</a> page.</p>
</div>
