Error in the SAML Authentication in Opensearch Dashoards

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

Describe the issue:
I configured the SAML Authentication for my Opensearch Dashboards in the Azure. If I type my Opensearch URL in the browser I can login successfully, but If I try to access the Opensearch Dashboards using the icon in the My Apps I receive the following error:

This is what I see in the browser:

{"statusCode":500,"error":"Internal Server Error","message":"Internal Error"} 

This is what I see in the dashboards host logs:

{"type":"log","@timestamp":"2024-04-25T17:48:25Z","tags":["error","plugins","securityDashboards"],"pid":25304,"message":"SAML IDP initiated authentication workflow failed: Error: failed to get token"}
{"type":"error","@timestamp":"2024-04-25T17:48:25Z","tags":[],"pid":25304,"level":"error","error":{"message":"Internal Server Error","name":"Error","stack":"Error: Internal Server Error\n    at HapiResponseAdapter.toError (/usr/share/opensearch-dashboards/src/core/server/http/router/response_adapter.js:127:19)\n    at HapiResponseAdapter.toHapiResponse (/usr/share/opensearch-dashboards/src/core/server/http/router/response_adapter.js:83:19)\n    at HapiResponseAdapter.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/response_adapter.js:79:17)\n    at Router.handle (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:175:34)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (internal/process/task_queues.js:95:5)\n    at handler (/usr/share/opensearch-dashboards/src/core/server/http/router/router.js:140:50)\n    at exports.Manager.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/toolkit.js:60:28)\n    at Object.internals.handler (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:46:20)\n    at exports.execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/handler.js:31:20)\n    at Request._lifecycle (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:371:32)\n    at Request._execute (/usr/share/opensearch-dashboards/node_modules/@hapi/hapi/lib/request.js:281:9)"},"url":"http://opensearch-dashboards-v1.<mycompany>.com/_opendistro/_security/saml/acs/idpinitiated","message":"Internal Server Error"}
{"type":"response","@timestamp":"2024-04-25T17:48:25Z","tags":[],"pid":25304,"method":"post","statusCode":500,"req":{"url":"/_opendistro/_security/saml/acs/idpinitiated","method":"post","headers":{"host":"opensearch-dashboards-v1.<mycompany>.com","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","sec-fetch-site":"cross-site","accept-language":"en-GB,en-US;q=0.9,en;q=0.8","accept-encoding":"gzip, deflate, br","sec-fetch-mode":"navigate","content-type":"application/x-www-form-urlencoded","origin":"https://login.microsoftonline.com","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15","referer":"https://login.microsoftonline.com/","content-length":"7569","connection":"keep-alive","sec-fetch-dest":"document"},"remoteAddress":"172.20.6.64","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15","referer":"https://login.microsoftonline.com/"},"res":{"statusCode":500,"responseTime":185,"contentLength":9},"message":"POST /_opendistro/_security/saml/acs/idpinitiated 500 185ms - 9.0B"}
{"type":"response","@timestamp":"2024-04-25T17:48:25Z","tags":[],"pid":25304,"method":"get","statusCode":302,"req":{"url":"/","method":"get","headers":{"user-agent":"ELB-HealthChecker/2.0","host":"172.20.7.180:443","connection":"close","accept":"*/*","accept-encoding":"*"},"remoteAddress":"172.20.7.180","userAgent":"ELB-HealthChecker/2.0"},"res":{"statusCode":302,"responseTime":1,"contentLength":9},"message":"GET / 302 1ms - 9.0B"}

Configuration:

This is my opensearch-security/config.yml configuration:

saml_auth_domain:
    http_enabled: true
    transport_enabled: false
    order: 1
    http_authenticator:
     type: saml
     challenge: true
     config:
      idp:
       metadata_url: "https://login.microsoftonline.com/<id>/federationmetadata/2007-06/federationmetadata.xml?appid=<appid>"
       entity_id: "https://sts.windows.net/<id>/"
      sp:
       entity_id: "https://opensearch-dashboards-v1.<mycompany>.com"
      kibana_url: "https://opensearch-dashboards-v1.<mycompany>.com"
      roles_key: "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
      exchange_key: "<key>"
    authentication_backend:
     type: noop

This is my opensearch_dashboards.yml configuration:

server.host: "0.0.0.0"
opensearch.hosts: https://opensearch-v1.<mycompany>.com:9200
opensearch.ssl.verificationMode: none
opensearch.username: admin
opensearch.password: mypassword
# opensearch.requestHeadersAllowlist: ["securitytenant","Authorization"]
opensearch.requestHeadersWhitelist: [authorization, securitytenant, WWW-Authenticate]

# Enable OpenID/saml authentication
opensearch_security.auth.type: "saml"
opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: [Private, Global]
opensearch_security.readonly_mode.roles: [kibana_read_only, readall, opensearch_dashboards_read_only]
#opensearch_security.readonly_mode.roles: [opensearch_dashboards_read_only]

# Use this setting if you are running opensearch-dashboards without https
opensearch_security.cookie.secure: false

# PLAT-1119 extend timeout to 12 hours (43200000ms)
opensearch_security.cookie.ttl: 43200000
opensearch_security.session.ttl: 43200000

server.xsrf.allowlist: ["/_opensearch/_security/saml/acs/idpinitiated", "/_opensearch/_security/saml/acs", "/_opensearch/_security/saml/logout", "/_opendistro/_security/saml/acs/idpinitiated", "/_opendistro/_security/saml/acs", "/_opendistro/_security/saml/logout", "/_plugins/_security/saml/acs/idpinitiated", "/_plugins/_security/saml/acs", "/_plugins/_security/saml/logout"]

server.maxPayloadBytes: 5242880
#logging.root.level: debug
#logging.verbose: true

Relevant Logs or Screenshots:

Hey @fernando.eickhoff

Perhaps try some like this.

authc:
      saml_auth_domain:
       http_enabled: true
       transport_enabled: true
       order: 1
       http_authenticator:
        type: saml
        challenge: true
        config:
         idp:
          metadata_url: https://zitadel.self-hosting.com/saml/v2/metadata
          entity_id: https://zitadel.self-hosting/saml/v2/metadata
         sp:
          entity_id: https://opensearch.domain.com:5601
         kibana_url: https://opensearch.domain.com:5601
         subject_key: Email <---- HERE
         roles_key: Role    <---- HERE
         exchange_key: AwqgAwIBAgICAY4wDQYJKoZIhvcNANjA2NT1UEChC0SOMETHING
       authentication_backend:
          type: noop

Another little tip is that I use SAML-Tracer on Chrome here

Hi @Gsmitt Thanks for your collaboration

The chrome extension is really helpful, I installed it to see if it can help me, but in your configuration I didn’t figure out any relevant difference that may help me.

I only see these 2 fields that you are using and I am not.

subject_key: Email <---- HERE
roles_key: Role    <---- HERE

Do you think these fields are relevant?

Hey,

TBH I’m not sure, I also seen your using AZURE/ Intra ID? I haven’t used that in a while but In my notes I used this…

Hope that helps

Your config refers to URL with HTTPS but the error reports the following link

http://opensearch-dashboards-v1.<mycompany>.com/_opendistro/_security/saml/acs/idpinitiated

Could you double check your Azure SAML app configuration?

Also, the entity_id has the URL. Did you name your exactly the same as the one in the entity_id?

Hi @pablo

When I read your message I felt the error was identified and it would be solved, but I could not identify any place in the configuration where it was using http instead of https. Anyway, then I followed the guide that @Gsmitt shared and the bug reported there made sense for me, so I replaced in the SAML configuration the _opendistro by _plugin and when I re-executed the security plugin to apply the new configs, the http error was not there anymore.

_plugin instead of _opendistro did not solve the error anyway, so I reverted back to _opendistro and the http in the logs really disappear.

What I have now, is this 401 error:

{"type":"response","@timestamp":"2024-04-29T20:47:57Z","tags":[],"pid":23559,"method":"get","statusCode":401,"req":{"url":"/_opendistro/_security/saml/acs","method":"get","headers":{"host":"opensearch-dashboards-v1.lkeymgmt.com","sec-fetch-site":"cross-site","sec-fetch-dest":"document","connection":"keep-alive","sec-fetch-mode":"navigate","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15","accept-language":"en-GB,en-US;q=0.9,en;q=0.8","accept-encoding":"gzip, deflate, br","referer":"https://myapps.microsoft.com/"},"remoteAddress":"172.20.13.217","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15","referer":"https://myapps.microsoft.com/"},"res":{"statusCode":401,"responseTime":3,"contentLength":9},"message":"GET /_opendistro/_security/saml/acs 401 3ms - 9.0B"}

Any clue? I think I progressed a bit now and I am wondering the 401 error is related to Roles and Roles Mapping.

Thanks for your help guys!

Hey,

401: Unauthorized think it relates to your issue. Did you use the SAML-Tracer on chrome? It should show you what going on in real time.

@fernando.eickhoff You can also try the OpenSearch documentation to verify the token that is provided by Azure.

Is the Azure app name the same as the one below?

      sp:
       entity_id: "https://opensearch-dashboards-v1.<mycompany>.com"

@Gsmitt this is the output of the saml tracer:

HTTP/1.1 302 Found
Location: https://opensearch-dashboards-v1.lkeymgmt.com/_opendistro/_security/saml/acs

and then:

HTTP/1.1 401 Unauthorized
osd-name: i-0628a2c837b285933.logstash.mgmt.use1

@pablo I guess the entity_id matches, looks the azure screenshot:

Thanks guys!

@fernando.eickhoff I see you’re using a reverse proxy in front of OpenSearch Dashboards. Is there a chance that you somehow filter incoming traffic at that endpoint?

thanks for the info