Azure SSO connection error with Opensearch Dashboards

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):

Opensearch :3.0.0

Docker version 28.3.0, build 38b7060

Describe the issue:

I am trying to connect to Azure SSO for Opensearch Dashboards getting the below error
in azure login page

Sign in

Sorry, but we’re having trouble signing you in.,

AADSTS50011: The reply URL 'https://dashboard-url:5601/_opendistro/_security/saml/acs' specified in the request does not match the reply URLs configured for the application 'https://dashboard-url.net:5601'. Make sure the reply URL sent in the request matches one added to your application in the Azure portal. 

Configuration:

dashboards.yml

server.name: opensearch-dashboards
server.host: "0.0.0.0"
server.port: 5601
server.ssl.enabled: true
server.ssl.certificate: /usr/share/opensearch-dashboards/config/certs/opensearch.pem
server.ssl.key: /usr/share/opensearch-dashboards/config/certs/opensearch-key.pem
server.ssl.certificateAuthorities: ["/usr/share/opensearch-dashboards/config/certs/root-ca.pem"]
opensearch.hosts: ["opensearch-url:9200"]
opensearch.ssl.verificationMode: none
opensearch.ssl.certificateAuthorities: ["/usr/share/opensearch-dashboards/config/certs/root-ca.pem"]

opensearch.username: "admin"
opensearch.password: "password"

# Request headers
#opensearch.requestHeadersWhitelist: ["authorization", "securitytenant"]
server.xsrf.allowlist: ["/_plugins/_security/saml/acs/idpinitiated", "/_opendistro/_security/saml/acs", "/_plugins/_security/saml/acs", "/_plugins/_security/saml/logout"]

opensearch_security.auth.type: "saml"
opensearch_security.auth.multiple_auth_enabled: true

# Multi-tenancy
opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"]

# Cookie settings
opensearch_security.cookie.secure: true

# Logging
logging.verbose: true
#logging.events: ["authentication", "security", "http", "error"]

security-config.yml

_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: false

    authc:
      basic_internal_auth_domain:
        description: "Internal authentication"
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: internal

      saml_auth_domain:
        description: "Azure AD SAML Authentication"
        http_enabled: true
        transport_enabled: false
        order: 1
        http_authenticator:
          type: saml
          challenge: true
          config:
            idp:
              pemtrustedcas_content: |-
                -----BEGIN CERTIFICATE-----
                XXXXXXXXXXXXXXXXXX
                -----END CERTIFICATE-----
              entity_id: "https://sts.windows.net/XXXXXXX/"
              metadata_url: "https://login.microsoftonline.com/XXXXXXX"
            sp:
              entity_id: "https://dashboard-url.net:5601"
            kibana_url: "https://dashboard-url.net:5601"
            subject_key: "user.userprincipalname"
            roles_key: "user.groups"
            name_id_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
            exchange_key: "8Fo_H8xxxvstUV6qahZwtzZU89XqsQYDKi4RWSrTO4o"
            roles_key_is_pattern: false
            verify_request_signature: false
        authentication_backend:
          type: noop

    authz:
      roles_from_myldap:
        description: "Map Azure AD groups to roles"
        http_enabled: true
        transport_enabled: false
        authorization_backend:
          type: noop

    do_not_fail_on_forbidden: false
    multi_rolespan_enabled: true
    hosts_resolver_mode: "ip-only"

I am using _pluigns instead of _opensdistro as suggested for later 2.0 versions

@sammy _plugins/_security is incorrect, please follow the documentation and use _opendistro in your Azure client and OpenSearch Dashboards whitelist/allowlist.

Since this is Azure, you don’t need this part as Azure certificates are signed with Enterprise CA certificates.

This error regards your Azure client. It should look like the example below.

@pablo made the changes as suggested in entra ID ,dashboards.yml and config.yml to _opendistro

Entra ID:

Basic SAML Configuration

Identifier (Entity ID) : opensearch_sso

Reply URL (Assertion Consumer Service URL) : https://dashboard-url:5601/_opendistro/_security/saml/acs

Sign on URL : https://dashboard-url:5601/

When I connect to sign on URL in browser I am getting below error

{“statusCode”:500,“error”:“Internal Server Error”,“message”:“Internal Error”}

@sammy Do you get HTTP 500 before connecting with Azure or after Azure authentication?
Do you see any SAML related errors in OpenSearch logs?

@pablo
Single sign on URL redirects to login.microsoft.com and gives an error 500

Error logs:

{“type”:“log”,“@timestamp”:“2025-07-24T16:11:16Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“ResponseError: security_exception: [security_exception] Reason: no permissions for [indices:admin/index_template/put] and User [name=admin, backend_roles=[admin], requestedTenant=null]\n at onBody (/usr/share/opensearch-dashboards/node_modules/@opensearch-project/opensearch/lib/Transport.js:426:23)\n at IncomingMessage.onEnd (/usr/share/opensearch-dashboards/node_modules/@opensearch-project/opensearch/lib/Transport.js:341:11)\n at IncomingMessage.emit (node:events:530:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at processTicksAndRejections (node:internal/process/task_queues:82:21) {\n meta: {\n body: { error: [Object], status: 403 },\n statusCode: 403,\n headers: {\n ‘x-opensearch-version’: ‘OpenSearch/3.0.0 (opensearch)’,\n ‘content-type’: ‘application/json; charset=UTF-8’,\n ‘content-length’: ‘361’\n },\n meta: {\n context: null,\n request: [Object],\n name: ‘opensearch-js’,\n connection: [Object],\n attempts: 0,\n aborted: false\n }\n }\n}”}
{“type”:“log”,“@timestamp”:“2025-07-24T16:23:07Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}
{“type”:“log”,“@timestamp”:“2025-07-24T16:23:11Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“SAML SP initiated authentication workflow failed: Error: Authentication Exception”}

Below are the security-config files:

roles.yml

_meta:
  type: "roles"
  config_version: 2

all_access_custom:
  reserved: false
  cluster_permissions:
    - "cluster_all"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: [""]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["__user__"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["security"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"

saml/kibana_user:
  reserved: false
  cluster_permissions:
    - "cluster_composite_ops_ro"
    - "cluster_monitor"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "read"
        - "search"
        - "get"
        - "view_index_metadata"
  tenant_permissions:
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"

admin:
  reserved: false
  cluster_permissions:
    - "cluster_all"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: [""]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["__user__"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["security"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"

security_admin:
  reserved: false
  cluster_permissions:
    - "cluster_all"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"

custom_kibana_server:
  reserved: false
  cluster_permissions:
    - "cluster_monitor"
  index_permissions:
    - index_patterns:
        - "*"
      allowed_actions:
        - "read"
        - "view_index_metadata"
        - "indices:admin/get"
        - "search"
        - "get"
        - "mappings:admin/get"
  tenant_permissions:
    - tenant_patterns:
        - "*"
      allowed_actions:
        - "kibana_all_read"

roles_mapping.yml

_meta:
  type: "rolesmapping"
  config_version: 2

admin:
  reserved: false
  users:
    - "admin"
  backend_roles:
    - "admin"
    - "Azure AD group"

all_access_custom:
  reserved: false
  backend_roles:
    - "Azure AD group"
  users:
    - "mail id"
  description: "Maps admin role to all_access"

tenants.yml

_meta:
  type: "tenants"
  config_version: 2

__user__:
  reserved: false
  description: "User Private Tenant"

It sounds like the yaml files aren’t taking. The yaml files seed the security index when a cluster is first created, but otherwise you need to use securityadmin.sh: Applying changes to configuration files - OpenSearch Documentation

@sammy As per the error, your admin user is missing indices:admin/index_template/put permission. This is a cluster-level permission. You need to add it to the cluster_permissions section in your admin role.

1 Like

Made the changes as suggested

roles.yml

_meta:
type: “roles”
config_version: 2

all_access_custom:
reserved: false
cluster_permissions:
- “cluster_all”
- “indices:admin/index_template/put”
index_permissions:
- index_patterns: [““]
allowed_actions:
- “indices_all”
tenant_permissions:
- tenant_patterns: [”“]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: [“user”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: [“security”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: [”
”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”

saml/kibana_user:
reserved: false
cluster_permissions:
- “cluster_composite_ops_ro”
- “cluster_monitor”
index_permissions:
- index_patterns: [““]
allowed_actions:
- “read”
- “search”
- “get”
- “view_index_metadata”
tenant_permissions:
- tenant_patterns: [”
”]
allowed_actions:
- “kibana_all_read”

admin:
reserved: false
cluster_permissions:
- “cluster_all”
- “indices:admin/index_template/put”
- “cluster:admin/ingest/pipeline/put”
- “indices:data/write/bulk”
index_permissions:
- index_patterns:
- “.kibana_"
- ".opensearch_dashboards_

allowed_actions:
- “all”
- index_patterns:
- “"
allowed_actions:
- “indices_all”
tenant_permissions:
- tenant_patterns: [“”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: [“user”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: [“security”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”
- tenant_patterns: ["
”]
allowed_actions:
- “kibana_all_read”
- “kibana_all_write”

security_admin:
reserved: false
cluster_permissions:
- “cluster_all”
index_permissions:
- index_patterns: [““]
allowed_actions:
- “indices_all”
tenant_permissions:
- tenant_patterns: [”
”]
allowed_actions:
- “kibana_all_read”

custom_kibana_server:
reserved: false
cluster_permissions:
- “cluster_monitor”
index_permissions:
- index_patterns:
- “"
allowed_actions:
- “read”
- “view_index_metadata”
- “indices:admin/get”
- “search”
- “get”
- “mappings:admin/get”
tenant_permissions:
- tenant_patterns:
- "

allowed_actions:
- “kibana_all_read”

roles_mapping.yml

_meta:
type: “rolesmapping”
config_version: 2

admin:
reserved: false
users:
- “admin”
backend_roles:
- “admin”
- “Azure AD group”

all_access_custom:
reserved: false
backend_roles:
- “Azure AD group”
users:
- “mail id”
description: “Maps admin role to all_access”

tenants.yml

_meta:
type: “tenants”
config_version: 2

user:
reserved: false
description: “User Private Tenant”

Global:
reserved: false
description: “Global shared tenant”

security:
reserved: true
description: “Security tenant”

Getting below error logs

https://dashboard-url:5601/auth/saml/login?redirectHash=false

{“statusCode”:500,“error”:“Internal Server Error”,“message”:“Internal Error”}

{
“type”: “log”,
@timestamp”: “2025-07-28T14:15:00Z”,
“tags”: [“error”, “opensearch”, “data”],
“pid”: 1,
“message”: “[security_exception]: no permissions for [indices:data/read/mget] and User [name=admin, backend_roles=[admin], requestedTenant=]”
}

“type”:“log”,“@timestamp”:“2025-07-28T14:49:00Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”
“type”:“log”,“@timestamp”:“2025-07-28T14:49:01Z”,“tags”:[“debug”,“metrics”],“pid”:1,“message”:“Refreshing metrics”
“Error: failed parsing SAML config”
at SecurityClient.getSamlHeader (securityDashboards/server/backend/opensearch_security_client.ts)
at processTicksAndRejections (internal/process/task_queues)
at securityDashboards/server/auth/types/saml/routes.ts
at Router.handle (server/http/router/router.js)
at handler (server/http/router/router.js)
at exports.Manager.execute (node_modules/@hapi/hapi/lib/toolkit.js)
at Object.internals.handler (node_modules/@hapi/hapi/lib/handler.js)
at exports.execute (node_modules/@hapi/hapi/lib/handler.js)
at Request._lifecycle (node_modules/@hapi/hapi/lib/request.js)
at Request._execute (node_modules/@hapi/hapi/lib/request.js)
“type”:“log”,“@timestamp”:“2025-07-28T14:49:01Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“Failed to get saml header: Error: Error: failed parsing SAML config”
“type”:“log”,“@timestamp”:“2025-07-28T14:49:01Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”

@sammy can you please add code tags around your configuration.

also, maybe the copy and paste is breaking this:

- index_patterns:
  - ""
allowed_actions:
  - “indices_all”

Can you confirm the permissions configured in admin role?

_meta:
  type: "roles"
  config_version: 2

all_access_custom:
  reserved: false
  cluster_permissions:
    - "cluster_all"
    - "indices:admin/index_template/put"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: [""]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["__user__"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["security"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"

saml/kibana_user:
  reserved: false
  cluster_permissions:
    - "cluster_composite_ops_ro"
    - "cluster_monitor"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "read"
        - "search"
        - "get"
        - "view_index_metadata"
  tenant_permissions:
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"

admin:
  reserved: false
  cluster_permissions:
    - "cluster_all"
    - "indices:admin/index_template/put"
    - "cluster:admin/ingest/pipeline/put"
    - "indices:data/write/bulk"
  index_permissions:
    - index_patterns:
        - ".kibana_*"
        - ".opensearch_dashboards_*"
      allowed_actions:
        - "all"
    - index_patterns:
        - "*"
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: [""]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["__user__"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["security"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"
        - "kibana_all_write"


security_admin:
  reserved: false
  cluster_permissions:
    - "cluster_all"
  index_permissions:
    - index_patterns: ["*"]
      allowed_actions:
        - "indices_all"
  tenant_permissions:
    - tenant_patterns: ["*"]
      allowed_actions:
        - "kibana_all_read"

custom_kibana_server:
  reserved: false
  cluster_permissions:
    - "cluster_monitor"
  index_permissions:
    - index_patterns:
        - "*"
      allowed_actions:
        - "read"
        - "view_index_metadata"
        - "indices:admin/get"
        - "search"
        - "get"
        - "mappings:admin/get"
  tenant_permissions:
    - tenant_patterns:
        - "*"
      allowed_actions

roles_mapping.yml

_meta:
  type: "rolesmapping"
  config_version: 2

admin:
  reserved: false
  users:
    - "admin"
  backend_roles:
    - "admin"
    - "Azure AD group"

all_access_custom:
  reserved: false
  backend_roles:
    - "Azure AD group"
  users:
    - "mail id"
  description: "Maps admin role to all_access"


tenants.yml

_meta:
  type: "tenants"
  config_version: 2

__user__:
  reserved: false
  description: "User Private Tenant"

Global:
  reserved: false
  description: "Global shared tenant"

security:
  reserved: true
  description: "Security tenant"

@sammy can you add the missing permission under cluster permissions in admin role and try again. According to docs this permission is a cluster level permissions.

You should add both:

indices:data/read/mget
indices:data/read/mget*

Made the changes as suggested still getting SAML error

type":“log”,“@timestamp”:“2025-07-29T05:29:31Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“StatusCodeError: Authorization Exception\n at respond (/usr/share/opensearch-dashboards/node_modules/elasticsearch/src/lib/transport.js:349:15)\n at checkRespForFailure (/usr/share/opensearch-dashboards/node_modules/elasticsearch/src/lib/transport.js:306:7)\n at HttpConnector. (/usr/share/opensearch-dashboards/node_modules/elasticsearch/src/lib/connectors/http.js:173:7)\n at IncomingMessage.wrapper (/usr/share/opensearch-dashboards/node_modules/lodash/lodash.js:4991:19)\n at IncomingMessage.emit (node:events:530:35)\n at endReadableNT (node:internal/streams/readable:1698:12)\n at processTicksAndRejections (node:internal/process/task_queues:82:21) {\n status: 403,\n displayName: ‘AuthorizationException’,\n path: ‘/_plugins/_security/tenantinfo’,\n query: {},\n body: undefined,\n statusCode: 403,\n response: ‘’,\n toString: [Function (anonymous)],\n toJSON: [Function (anonymous)]\n}”}
{“type”:“log”,“@timestamp”:“2025-07-29T05:29:31Z”,“tags”:[“warning”,“environment”],“pid”:1,“message”:“Detected an unhandled Promise rejection.\nAuthorization Exception :: {"path":"/_plugins/_security/tenantinfo","query":{},"statusCode":403,"response":""}”}

{“type”:“log”,“@timestamp”:“2025-07-29T05:30:21Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}
[agentkeepalive:deprecated] options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead
Error: failed parsing SAML config
at SecurityClient.getSamlHeader (/usr/share/opensearch-dashboards/plugins/securityDashboards/server/backend/opensearch_security_client.ts:214:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at /usr/share/opensearch-dashboards/plugins/securityDashboards/server/auth/types/saml/routes.ts:80:30
at Router.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:174:44)
at handler (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:140:50)
at exports.Manager.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/toolkit.js:60:28)
at Object.internals.handler (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:46:20)
at exports.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:31:20)
at Request._lifecycle (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:371:32)
at Request._execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:281:9)
{“type”:“log”,“@timestamp”:“2025-07-29T05:30:23Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“Failed to get saml header: Error: Error: failed parsing SAML config”}
{“type”:“log”,“@timestamp”:“2025-07-29T05:30:24Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}

Alos with local login as admin user I get the below result,

curl -k -u admin:password https://dashboard-url:9200/_plugins/_security/whoami
{“dn”:null,“is_admin”:false,“is_node_certificate_request”:false}

@pablo any suggestion on the issue, I am still not able to connect to Azure SSO getting unauthorized: 500 error

Also, with local login as admin user I get the below result,

curl -k -u admin:password https://dashboard-url:9200/_plugins/_security/whoami
{“dn”:null,“is_admin”:false,“is_node_certificate_request”:false}

Error logs for Dashboards

[agentkeepalive:deprecated] options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead
Error: failed parsing SAML config
at SecurityClient.getSamlHeader (/usr/share/opensearch-dashboards/plugins/securityDashboards/server/backend/opensearch_security_client.ts:214:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at /usr/share/opensearch-dashboards/plugins/securityDashboards/server/auth/types/saml/routes.ts:80:30
at Router.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:174:44)
at handler (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:140:50)
at exports.Manager.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/toolkit.js:60:28)
at Object.internals.handler (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:46:20)
at exports.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:31:20)
at Request._lifecycle (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:371:32)
at Request._execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:281:9)
{“type”:“log”,“@timestamp”:“2025-07-31T05:20:18Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“Failed to get saml header: Error: Error: failed parsing SAML config”}
{“type”:“log”,“@timestamp”:“2025-07-31T05:20:18Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}

hey @sammy ,

Are you getting any other errors? What kind of certs are you using? Do both Entra id’s match?

Have you had any progression,

Leeroy.

Still the same error. Using internal CA certs. Yes both the entra id’s in config.yml and azure AD match

{“type”:“log”,“@timestamp”:“2025-08-01T14:22:44Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}
{“type”:“log”,“@timestamp”:“2025-08-01T14:22:45Z”,“tags”:[“debug”,“metrics”],“pid”:1,“message”:“Refreshing metrics”}
[agentkeepalive:deprecated] options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead
Error: failed parsing SAML config
at SecurityClient.getSamlHeader (/usr/share/opensearch-dashboards/plugins/securityDashboards/server/backend/opensearch_security_client.ts:214:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at /usr/share/opensearch-dashboards/plugins/securityDashboards/server/auth/types/saml/routes.ts:80:30
at Router.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:174:44)
at handler (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:140:50)
at exports.Manager.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/toolkit.js:60:28)
at Object.internals.handler (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:46:20)
at exports.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:31:20)
at Request._lifecycle (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:371:32)
at Request._execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:281:9)
{“type”:“log”,“@timestamp”:“2025-08-01T14:22:46Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“Failed to get saml header: Error: Error: failed parsing SAML config”}

Hey @sammy ,

I took some time and done some testing with your setup, and replicated the issues you’re having with Error: failed parsing SAML config.

When I created an application in azure it sets some claims by default and then allows for you to add additional claims if needed.

Updating both your subject_key and your roles_key to use the claim names created -

When ran allows your setup to work. This is because it requires the claim name to exist and match.

You can if needed add additional claims, check the claims you do have. Which would allow you to create claim names for user.userprincipalname and user.groups.

I would also suggest using another claim for subject name such as http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress to get a more user readable name, however I will leave that decision with you.

Leeroy.

subject_key: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
roles_key: “http://schemas.microsoft.com/ws/2008/06/identity/claims/groups

Using this in config.yml

Azure AD

Still the same error

{“type”:“log”,“@timestamp”:“2025-08-12T05:21:56Z”,“tags”:[“debug”,“metrics”],“pid”:1,“message”:“Refreshing metrics”}
Error: failed parsing SAML config
at SecurityClient.getSamlHeader (/usr/share/opensearch-dashboards/plugins/securityDashboards/server/backend/opensearch_security_client.ts:214:15)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at /usr/share/opensearch-dashboards/plugins/securityDashboards/server/auth/types/saml/routes.ts:80:30
at Router.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:174:44)
at handler (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:140:50)
at exports.Manager.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/toolkit.js:60:28)
at Object.internals.handler (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:46:20)
at exports.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:31:20)
at Request._lifecycle (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:371:32)
at Request._execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:281:9)
{“type”:“log”,“@timestamp”:“2025-08-12T05:21:58Z”,“tags”:[“error”,“plugins”,“securityDashboards”],“pid”:1,“message”:“Failed to get saml header: Error: Error: failed parsing SAML config”}
{“type”:“log”,“@timestamp”:“2025-08-12T05:21:58Z”,“tags”:[“debug”,“http”,“server”,“OpenSearchDashboards”,“cookie-session-storage”],“pid”:1,“message”:“Error: Unauthorized”}

Hey @sammy ,

You would now use

subject_key: “emailaddress”
roles_key: “groups”

Leeroy.

Hey @sammy ,

I forgot to note I also fixed a few errors in your config

  • I added acs under config -
  • I removed verify_request_signature.
  • I removed do_not_fail_on_forbidden, default is false as per - Multi-tenancy configuration - OpenSearch Documentation
  • I removed roles_key_is_pattern.
  • I removed multi_rolespan_enabled.
  • I removed name_id_format: “urn:oasis:names:tc:SAML:2.0:nameid-format:persistent”

I suggest you first comment out the sections that are not required to run - see SAML - OpenSearch Documentation . Then you can test saml first to get authenticated. Then add any additional config back in correctly one by one not to get another 500 error. In addition you could remove roles and mappings to first test connection.

Also see this document - Troubleshoot SAML - OpenSearch Documentation you can use the log4j2.properties to get better logs back so we can figure out what else might be blocking you.

Leeroy.

1 Like

It worked after removing those lines as suggested and making changes based on Opensearch documentation, thank you for your assistance.

2 Likes