Opensearch dashboards getting No 'Basic Authorization' header, send 401 and 'WWW-Authenticate Basic' when trying to login via SSO

I have configured logging via Keycloack,and when trying to login with SSO to dashboards, I am getting 502 Bad Gateway and “No ‘Basic Authorization’ header, send 401 and 'WWW-Authenticate Basic” in the logs for the Opensearch.

Here is my opensearch_dashboards.yml file

        server.host: "0.0.0.0"
        opensearch.ssl.verificationMode: none
        opensearch.username: ${data.vault_generic_secret.opensearch_credentials.data["username"]}
        opensearch.password: ${data.vault_generic_secret.opensearch_credentials.data["password"]}
        opensearch.requestHeadersAllowlist: ["Authorization", "securitytenant", "WWW-Authenticate" ]
        opensearch.ssl.certificateAuthorities: ["/usr/share/dashboards/certs/ca.crt"]
        server.ssl.certificateAuthorities: 	["/usr/share/dashboards/certs/ca.crt"]
        opensearch_security.multitenancy.enabled: true
        opensearch_security.readonly_mode.roles: ["readall"]
        
        opensearch_security.openid.client_id: ${keycloak_openid_client.this.client_id}
        opensearch_security.openid.client_secret: "${keycloak_openid_client.this.client_secret}"
        opensearch_security.auth.type: ["basicauth","openid"]
        opensearch_security.auth.multiple_auth_enabled: true  
        opensearch_security.openid.connect_url: "https://auth.dev.xxx.cloud/auth/realms/employee/.well-known/openid-configuration" 
        opensearch_security.openid.base_redirect_url: xxx
        opensearch_security.openid.verify_hostnames: false
        opensearch_security.openid.scope: openid profile email roles
        opensearch_security.openid.header: "Authorization"

Here is my config.yml

_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    http:
      anonymous_auth_enabled: false
    authc:
      basic_internal_auth_domain:
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: internal
      openid_auth_domain:
        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: xxx
            jwks_uri: xxx
        authentication_backend:
          type: noop

Any suggestions on what I can try? Thanks in advance.

@dav.m I have some questions about your configs.

What’s the reason for opensearch.ssl.certificateAuthorities and server.ssl.certificateAuthorities as opensearch.ssl.verificationMode is set to none and server.ssl.enabled is not configured?

I’ve noticed in the kibana.yml that opensearch_security.openid.connect_url is set to HTTPS address. Do you use self-signed certificates in Keycloak? Do you use a reverse proxy in front of the Keycloak?

What version of Keycloak do you use?

It is public domain,we use public certs.No we don’t use a reverse proxy. Keycloak version is the latest(22.04).

@dav.m Are you getting redirected to the Keycloack’s login page?

Yes this process is working correctly, i am getting redirected to Keycloacks login page, and after that I can see successful opened session in keycloack

@dav.m The SSL in openid is not enabled. You need to configure openid_connect_idp.enable_ssl.
As per documentation, the default value is false.

I’ve enabled the openid_connect_idp.enable_ssl , and after that, I’m encountering the error:

{"statusCode":401,"error":"Unauthorized","message":"Unauthorized"}

in the web interface after logging in with SSO. Additionally, the error log about “No ‘Basic Authorization’ header” still persists. Thanks.

@dav.m This might be caused by missing roles in Keycloack’s JWT token. Did you configure User Realm Role in Client Scopes?

I believe it is configured normally. Here is the JWT token output, where you can see the two roles: “all_access,” which is the default for OpenSearch, and “admin_role,” the custom role I created with all permissions.
Screenshot from 2023-10-12 16-32-57

@dav.m Have you assigned admin_role as backend role in roles_mapping.yml?
If you want to use built-in backend roles then try assigning either kibanauser or admin in Keycloak.

Let me share with you the contents of the internal_users.yml , roles.yml , and roles_mapping.yml files. Could you please review them and let me know if they are correct or not?

internal_users.yml
_meta:
  type: "internalusers"
  config_version: 2

admin:
  hash: "{{ admin_password_hash }}"
  reserved: true
  hidden: false
  backend_roles:
  - "admin_role"
roles.yml
_meta:
  type: "roles"
  config_version: 2

admin_role:
  reserved: true
  hidden: false
  cluster_permissions:
    - '*'
  index_permissions:
    - index_patterns:
        - '*'
      allowed_actions:
        - "admin"
  tenant_permissions:
    - tenant_patterns:
        - '*'
      allowed_actions:
        - '*'
  static: true
roles_mapping.yml
_meta:
  type: "rolesmapping"
  config_version: 2

all_access:
  reserved: true
  hidden: false
  users:
    - "admin"

admin_role:
  reserved: true
  hidden: false
  backend_roles:
  - "admin_role"

@dav.m The User Realm Role configuration is crucial. The Multivalued option must be set to true (On). If that is set to false, Keycloak will send it as a single array and the OpenSearch security plugin won’t understand it.

Could you share a screenshot of your User Realm Role configuration? You’ll find it in Client Scopes.

Regarding the roles mapped to the Keycloak user, please use admin instead of all_access as admin is a built-in backend role.

The logic of the OpenID and OpenSearch roles mapping is as follows.

  1. Keycloak’s role is assigned to the Keycloak’s user in Keycloak.
  2. The OpenSearch role is created for a Keycloak user.
  3. The Keycloak’s role is assigned (mapped) as a backend role to the OpenSearch role.

I am not using realm roles, just using that client roles admin_role and all_access.

@dav.m Have you tried following my example and testing it in your environment?

If you mean examples which you shared with me about OpenID connect.For sure I tested them in my environment , but still getting same error.

Is this ‘admin’ is custom permission group?

Have you tried assigning the “admin” role instead of all_access to this test user?

Screenshot from 2023-10-12 16-32-57

Hey @pablo , apologies for the delayed response. I took a break from Opensearch for a while, but now I’m back and ready to dive back in.

Yes the “admin” is custom group and here is the config file for him:


_meta:
  type: "actiongroups"
  config_version: 2

admin:
  allowed_actions:
    - "unlimited"

As for the “admin_role,” initially, I intended to use only that role. However, after some testing, I decided to also include the “all_access” role to see if that resolves the issue.

I want to clarify something about the error message I’m encountering in the web interface after logging in with SSO. It’s a WARNING message indicating the absence of a Basic auth header. However, I want to emphasize that I am indeed using Basic auth, and it’s functioning successfully.

@dav.m Have you tried using admin instead of all_access? The admin is a backend built-in role in OpenSearch.

When you authenticate with an external IdP (i.e. LDAP, SAML, OpenID) all the roles sent by the IdP are called backed roles. To use these roles, they must be mapped with OpenSearch’s roles in the roles_mapping.yml file.

The exception is built-in roles (i.e. admin, kibanauser, logstash etc) which can be defined directly in the IdP’s user and doesn’t have to be mapped in the roles_mapping.yml file.