No 'Authorization' header, send 401 and 'WWW-Authenticate Basic' with NGINX proxy

Versions (): v 3.1.0

Describe the issue:

Hello, i have lot of following logs (~15) during the auth (active directory) with opensearch dashboards behind NGINX. The auth is in success and the authorization is OK also.


[2025-10-01T17:05:40,804][WARN ][o.o.s.a.BackendRegistry  ] [toto.com] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'

[2025-10-01T17:05:40,804][INFO ][audit                    ] [toto.com] {"audit_cluster_name":"cluster-01","audit_node_name":"toto.com","audit_rest_request_method":"HEAD","audit_category":"FAILED_LOGIN","audit_request_origin":"REST","audit_node_id":"Wz0p-N_mTICnKbf3pUpjMQ","audit_request_layer":"REST","audit_rest_request_path":"/","@timestamp":"2025-10-01T15:05:40.804+00:00","audit_request_effective_user_is_admin":false,"audit_format_version":4,"audit_request_remote_address":"10.XX.XX.XX","audit_node_host_address":"10.XX.XX.XX","audit_rest_request_headers":{"Connection":["keep-alive"],"Host":["toto.com:9200"],"Content-Length":["0"],"x-opensearch-product-origin":["opensearch-dashboards"]},"audit_request_effective_user":"<NONE>","audit_node_host_name":"10.XX.XX.XX"}

Without NGINX, it’s OK

I tried to change

  • order between ldap and internal,
  • http_authenticator challenge true and false

Configuration:

config opensearch

config:
  dynamic:
    http:
      xff:
        enabled: true
        internalProxies: '.*'
        remoteIpHeader: "X-Forwarded-For"
    authc:
      basic_internal_auth_domain:
        order: 1
        description: "HTTP basic authentication using the internal user database"
        http_enabled: true
        transport_enabled: true
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: internal
      ldap:
        http_enabled: true
        transport_enabled: false
        order: 0
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: ldap
          config:
          ...
    authz:
      ldap:
        http_enabled: true
        transport_enabled: true
        authorization_backend:
          type: ldap
          config:
          ...

config NGINX
...
  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass https://opensearch_dashboards;
    proxy_ssl_verify       off;
  # Response buffer settings
    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;
  }
...
1 Like

@Guillaume have you tried adding proxy_set_header Authorization $http_authorization; to the nginx config? This error usually occurs when opensearch receives request without Authorization header.

Also only one challenge should be set to true, in your case can you set ldap to false

1 Like

Thx for your help @Anthony but i have the same issue.

i added the following option in my nginx conf and i restarted nginx

    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;

regards

Guillaume

@Guillaume can you share your opensearch_dashboards.yml file (please redact any sensitive details).

1 Like

What version are you using? There is a fix for this in 3.1.0: https://github.com/opensearch-project/security/pull/5377

1 Like

Hello @Anthony please see below my opensearch dashboard conf:

server.port: 5601
server.ssl.enabled: true
server.host: 0.0.0.0
opensearch.hosts: ['https://myhost1:9200', 'https://myhost2:9200', 'https://myhost3:9200']
opensearch.ssl.verificationMode: full
opensearch.username: "xxxxxxxxx"
opensearch.password: "xxxxxxxxx"
opensearch.requestHeadersWhitelist: [ authorization,securitytenant ]
opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"]
opensearch_security.readonly_mode.roles: ["kibana_read_only"]
server.ssl.certificate: /etc/ssl/opensearch-dashboards/xxxxxxxxxxxxxxxx
server.ssl.key: /etc/ssl/opensearch-dashboards/xxxxxxxxxxxxxxxxx
opensearch.ssl.certificateAuthorities: ["/etc/ssl/opensearch-dashboards/xxxxxxxxxxx"]

1 Like

Hello @cwperks I have this version.

dpkg -l | grep opensearch
ii  opensearch                     3.1.0                          amd64        An open source distributed and RESTful search engine
ii  opensearch-dashboards          3.1.0                          amd64        Open source visualization dashboards for OpenSearch

Regards

Guillaume

@Guillaume can you try setting challenge from true to false on the basic auth backend?

You only need to set that to true if you want to make credential-less requests directly to the OpenSearch backend and have the browser prompt to enter credentials.

Make sure to use the securityadmin.sh tool when making changes to the yaml files.

1 Like

Hello @cwperks is it like that ? i have the same issue

    authc:
      basic_internal_auth_domain:
        order: 1
        description: "HTTP basic authentication using the internal user database"
        http_enabled: true
        transport_enabled: true
        http_authenticator:
          type: basic
          challenge: false
          config: {}
        authentication_backend:
          type: internal
          config: {}
      ldap:
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: ldap
          config:



1 Like

@cwperks i use securityadmin.sh to update config file.

Regards

Guillaume

What’s the output of the script?

I ask because the only place this is logged in 3.1 is in a block where its checking if challenge is set to true: security/src/main/java/org/opensearch/security/auth/BackendRegistry.java at 3.1 · opensearch-project/security · GitHub

1 Like

@Guillaume another great way to check which security configuration is loaded into security index is using the API, using the following command:

GET _plugins/_security/api/securityconfig
1 Like

@cwperks I hadn’t noticed, but with challenge to false, I don’t have any more 401 but an other logs.

[2025-10-21T09:59:33,096][WARN ][o.o.s.a.BackendRegistry  ] [myhost] Authentication finally failed for null from xxx.xxx.xxx.xxx:46150
[2025-10-21T09:59:33,097][INFO ][audit                    ] [myhost] {"audit_cluster_name":"mycluster","audit_node_name":"myhost","audit_rest_request_method":"GET","audit_category":"FAILED_LOGIN","audit_request_origin":"REST","audit_node_id":"Wz0p-N_mTICnKbf3pUpjMQ","audit_request_layer":"REST","audit_rest_request_path":"/.kibana/_doc/config:3.2.0","@timestamp":"2025-10-21T07:59:33.096+00:00","audit_request_effective_user_is_admin":false,"audit_format_version":4,"audit_request_remote_address":"10.252.143.31","audit_node_host_address":"xxx.xxx.xxx.xxx","audit_rest_request_headers":{"Connection":["keep-alive"],"x-opaque-id":["963e8435-3953-46a0-a0a0-a50006fefa16"],"Host":["myhost:9200"],"x-opensearch-product-origin":["opensearch-dashboards"],"user-agent":["opensearch-js/2.13.0 (linux 6.1.0-35-amd64-x64; Node.js v20.18.3)"]},"audit_node_host_name":"xxx.xxx.xxx.xxx"}

ldap auth or internal auth is still in success.

OPENSEARCH_JAVA_HOME=/usr/share/opensearch/jdk /usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh -f /etc/opensearch/opensearch-security/config.yml -icl -nhnv  -cert /etc/ssl/opensearch/mycert.cert -key /etc/ssl/opensearch/mykey.pkcs8 -cacert /etc/ssl/opensearch/ca.pem
Security Admin v7
Will connect to localhost:9200 ... done
Connected as "CN=myhost"
ERR: Seems you use a node certificate which is also an admin certificate
     That may have worked with older OpenSearch Security versions but it indicates
     a configuration error and is therefore forbidden now.
OpenSearch Version: 3.2.0
Contacting opensearch cluster 'opensearch' and wait for YELLOW clusterstate ...
Clustername: mycluster
Clusterstate: GREEN
Number of nodes: 3
Number of data nodes: 3
.opendistro_security index already exists, so we do not need to create one.
Populate config from /root
Will update '/config' with /etc/opensearch/opensearch-security/config.yml
   SUCC: Configuration for 'config' created or updated
SUCC: Expected 1 config types for node {"updated_config_types":["config"],"updated_config_size":1,"message":null} is 1 (["config"]) due to: null
SUCC: Expected 1 config types for node {"updated_config_types":["config"],"updated_config_size":1,"message":null} is 1 (["config"]) due to: null
SUCC: Expected 1 config types for node {"updated_config_types":["config"],"updated_config_size":1,"message":null} is 1 (["config"]) due to: null
Done with success

An extract from GET _plugins/_security/api/securityconfig @Anthony

    "basic_internal_auth_domain": {
      "http_enabled": true,
      "order": 1,
      "http_authenticator": {
        "challenge": false,
        "type": "basic",
        "config": {}
      },
      "authentication_backend": {
        "type": "internal",
        "config": {}
      },
      "description": "HTTP basic authentication using the internal user database"
    }

Ldap challenge is also false

Maybe is a detail but, without nginx, i have one Authentication finally failed just before to send my credential. With Nginx , i have a loop of 401 (~15)

Thanks you very much for your help

Regards

Guillaume

1 Like