Nested claim for JWT auth, can't find roles

I am using OpenSearch 3.2.0 and OpenSearch Dashboards 3.2.0, set up via Podman as an OpenSearch Cluster with three nodes on three different VM Linux Servers. I am using a Keycloak-Instance on a different VM for Authentication and Role-Management. The Cluster itself works fine and the nodes are communicating with each other.

The problem is, if I want to access my roles “realm_access.roles” (for using the role “opensearch-access”), there is an error returned that the AbstractHTTPJwtAuthenticator couldn’t get the roles. I researched and found out that apparently since OpenSearch Version 3.1.0 the claim for nested roles for JWT auth should be supported, e.g. described here https://github.com/opensearch-project/security/pull/5355. Maybe the structure of my roles inside my JWT is something different and not yet supported.

config.yml (for security)

In my config.yml I tried different versions for “roles_key” but none of them worked. If i select some other property like just “aud” and just for testing configured the proper role for “osdashboards_private”, it worked like a charm, no problems there. I think the problem has something to do with the roles being in a nested array of strings.

_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    authc:
      openid_auth_domain:
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: openid
          challenge: false
          config:
            subject_key: preferred_username
            roles_key: realm_access.roles
            openid_connect_url: <URL>
            required_audience: <VALUE>
        authentication_backend:
          type: noop

And I also tried writing “roles_key” like this:

            roles_key: "realm_access.roles"

And I also tried this:

            roles_key:
              - realm_access
              - roles

And I tried this:

            roles_key:
              - realm_access.roles

JWT JSON Structure

The relevant part of my returned JWT token looks like this:

{
  ...
  "aud": [
    "osdashboards_private",
    "account"
  ],
  "typ": "Bearer",
  "acr": "1",
  "allowed-origins": [
    ""
  ],
  "realm_access": {
    "roles": [
      "default-role",
      "opensearch-access",
      "some-other-role",
    ]
  }
  ...
}

Log from AbstractHTTPJwtAuthenticator

[2025-09-29T06:17:55,581][WARN ][o.o.s.a.h.j.AbstractHTTPJwtAuthenticator] [opensearch-node-1] Failed to get roles from JWT claims with roles_key ‘[realm_access.roles]’. Check if this key is correct and available in the JWT payload.

Should the current support of nested roles claim from JWT in 3.2.0 support the claim of the roles stated below? Or do I have a wrong configuration?

Thank you for your help!

@coding-jodl Looking at the token you provide the type seems to be incorrect. OpenID login flow, OpenSearch/Dashboards works off the ID token, which should look as follows (note the “typ”: “ID”):

{
  "exp": 1699880265,
  "iat": 1699879965,
  "auth_time": 0,
  "jti": "f972edee-d607-49b4-af49-14ca941a4886",
  "iss": "http://keycloak:8080/realms/Support_Prototype",
  "aud": "opensearch",
  "sub": "06dfbe62-7aca-401d-8162-b553292c5680",
  "typ": "ID",
  "azp": "opensearch",
  "session_state": "b9c1adea-48ef-4dd6-a220-b210a10fff16",
  "acr": "1",
  "sid": "b9c2adea-47ef-4dd6-a220-b210a10fff16",
  "resource_access": {
    "grafana-oauth": {
      "roles": [
        "admin"
      ]
    },
    "opensearch": {
      "roles": [
        "all_access"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "email_verified": true,
  "roles": [
    "default-roles_support_prototype",
    "offline_access",
    "all_access",
    "uma_authorization"
  ],
  "name": "admin user",
  "preferred_username": "adminuser",
  "given_name": "admin",
  "family_name": "user",
  "email": "admin@mymail.com"
}

I believe in keycloak this is done going to Client scopes → roles → Mappers → realm roles and selecting Add to ID token

@Anthony Thank you very much, this was the main issue and could be solved by adding the property to the ID token!

Also it seems that for nested claims you have to write it as a yaml list like below. The dot-notation didn’t work for me.

    roles_key:
      - realm_access
      - roles
2 Likes