Kibana OpenID Connect does not redirect to IDP (IdentityServer4)

I’ve been trying to get this working for a few days now, but no luck. The expectation here is that if the user is not authenticated, Kibana should redirect to the IDP login endpoint. This does not happen. Instead, I keep getting the following response when I try to access Kibana for the first time:

{“statusCode”:401,“error”:“Unauthorized”,“message”:“Unauthorized”}

The logs indicate that Kibana does route from the root to the oidc route. But from there, it does not redirect to the idp auth endpoint for some reason. I should add that if I manually inject a valid token to the request, Kibana does allow access using the user in the token.

The redirect to the identity provider does not happen.

Any help would be greatly appreciated!

Kibana logs:

{“type”:“log”,“timestamp”:“2020-12-18T00:07:30Z”,“tags”:[“debug”,“http”,“server”,“Kibana”,“cookie-session-storage”],“pid”:11360,“message”:“Error: Unauthorized”}

{“type”:“response”,“timestamp”:“2020-12-18T00:07:30Z”,“tags”:,“pid”:11360,“method”:“get”,“statusCode”:401,“req”:{“url”:“/favicon.ico”,“method”:“get”,“headers”:{“cache-control”:“no-cache”,“connection”:“Keep-Alive”,“pragma”:“no-cache”,“accept”:“image/avif,image/webp,image/apng,image/,/;q=0.8",“accept-encoding”:“gzip, deflate, br”,“accept-language”:“en-US,en;q=0.9”,“host”:“”,“max-forwards”:“10”,“referer”:“/auth/openid/login?nextUrl=%2F”,“user-agent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36”,“sec-ch-ua”:“"Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"”,“sec-ch-ua-mobile”:“?0”,“sec-fetch-site”:“same-origin”,“sec-fetch-mode”:“no-cors”,“sec-fetch-dest”:“image”,“x-original-url”:“/favicon.ico”,“x-forwarded-for”:“<>”,“x-arr-ssl”:“”,“x-arr-log-id”:“7f42fe43-8902-4bcd-8c32-8ea1c533d80a”},“remoteAddress”:"<**>”,“userAgent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36”,“referer”:“/auth/openid/login?nextUrl=%2F”},“res”:{“statusCode”:401,“responseTime”:0,“contentLength”:9},“message”:“GET /favicon.ico 401 0ms - 9.0B”}

config.yml
authc:
basic_internal_auth_domain:
description: “Authenticate via HTTP Basic against internal users database”
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: <subject_key>
roles_key: <role_key>
openid_connect_url: /.well-known/openid-configuration
enable_ssl: true
verify_hostnames: false
pemtrustedcas_filepath: “”
authentication_backend:
type: noop
authz:

kibana.yml
opendistro_security.auth.type: “openid”
opendistro_security.openid.connect_url: “/.well-known/openid-configuration”
opendistro_security.openid.client_id: <client_id>
opendistro_security.openid.client_secret:
opendistro_security.openid.scope: “openid profile web.api”
opendistro_security.openid.base_redirect_url: “<kibana_host>”
opendistro_security.openid.root_ca: “<path_to_cert>”
opendistro_security.openid.verify_hostnames: false

I’m using the latest version of opendistro ES and Kibana and also running into this issue.

Very similar setup as described above, basically everything taken from the documentation verbatim.

1 Like

These open issues on github seem related to this.

it looks like the oidc auth handler route isn’t being parsed correctly in the kibana plugin.

In case anyone finds this thread via search: this ticket is related too.

@plele-ssc did you try solution in Missing important parameter in OpenID configuration

Yes. It didn’t help.

@plele-ssc Just to confirm the full openid_connect_url was actually used in both files but first part was redacted?
So full url looks something like this? (keycloak example):
https://<idp_host>/auth/realms/<realm_name>/.well-known/openid-configuration

Yes, that’s right. Full url was added in both config files, but host was redacted here.

@plele-ssc, did you manage to solve this? I’m having the same issue as you but since they did some GitHub “housekeeping” I’m struggling to find any further advice.

@joshblease I struggled to find advice even before the housekeeping, tbh. It seems to work well with keycloak, but not that much information out there about IdentityServer.

Anyhow - I was not able to solve this, and ended up not implementing OIDC login.

Okay @plele-ssc, I managed to figure it out but it wasn’t easy and I’ve had to fork the security plugin repo to come up with a “fix” (my knowledge of node is limited and I can’t commit back a change of good quality). I’ll document my solution here:

I use self signed certs for Elasticsearch & Kibana, however I am using Okta as my IdP so your mileage may vary. The only ways to authenticate in my setup are with client certs or SSO.

This is my ES security config (make sure to use securityadmin.sh to load the new config and refresh the cache if you change this:

_meta:
  type: "config"
  config_version: 2
config:
  dynamic:
    kibana:
      multitenancy_enabled: true
      server_username: kibanaserver
      index: '.kibana'
    do_not_fail_on_forbidden: false
    authc:
      clientcert_auth_domain:
        description: "Authenticate via SSL client certificates"
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          type: clientcert
          config:
            username_attribute: cn
          challenge: false
        authentication_backend:
          type: noop
      openid_auth_domain:
        description: "Authenticate via OAuth"
        http_enabled: true
        transport_enabled: true
        order: 2
        http_authenticator:
          type: openid
          challenge: false
          config:
            subject_key: name
            roles_key: groups
            openid_connect_url: https://dev-999999.okta.com/oauth2/default/.well-known/openid-configuration
        authentication_backend:
          type: noop

The Kibana config is as follows (there may be some unnecessary config here but it works :man_shrugging:t3:):

elasticsearch.preserveHost: true
server.xsrf.whitelist: ["/_opendistro/_security/saml/acs", "/_opendistro/_security/saml/logout", "/_opendistro/_security/api/authtoken"]
elasticsearch.ssl.certificate: /etc/kibana/kibana.crt
elasticsearch.ssl.key: /etc/kibana/kibana.key
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/ca.crt" ]
elasticsearch.ssl.verificationMode: certificate
opendistro_security.multitenancy.enabled: true
opendistro_security.multitenancy.tenants.enable_global: true
opendistro_security.multitenancy.tenants.enable_private: false
opendistro_security.multitenancy.enable_filter: false
elasticsearch.requestHeadersWhitelist: ["Authorization", "security_tenant", "jwtToken", "securitytenant"] 
opendistro_security.auth.type: "openid"
opendistro_security.openid.connect_url: "https://dev-999999.okta.com/oauth2/default/.well-known/openid-configuration"
opendistro_security.openid.client_id: "id-from-idp"
opendistro_security.openid.client_secret: "secret-from-idp"
opendistro_security.openid.base_redirect_url: "https://kibana.myhost.com/" 
opendistro_security.openid.header: "Authorization"

I finally modified the OpenID plugin which is found at /usr/share/kibana/plugins/opendistroSecurityKibana/server/auth/types/openid. The problem is that the plugin doesn’t register then endpoints before kibana starts up and so it never works. I replace the init method in openid_auth.js with the following (be sure to remove the async keyword too)

init() {
    try {
        this.openIdAuthConfig.authorizationEndpoint = "https://dev-999999.okta.com/oauth2/default/v1/authorize";
        this.openIdAuthConfig.tokenEndpoint = "https://dev-999999.okta.com/oauth2/default/v1/token";
        this.openIdAuthConfig.endSessionEndpoint = "https://dev-999999.okta.com/oauth2/default/v1/logout";
        const routes = new _routes.OpenIdAuthRoutes(this.router, this.config, this.sessionStorageFactory, this.openIdAuthConfig, this.securityClient, this.coreSetup, this.wreckClient);
        routes.setupRoutes();
    } catch (error) {
        this.logger.error(error); // TODO: log more info
        throw new Error('Failed when trying to obtain the endpoints from your IdP');
    }
}

I’m trying to build the new plugin now at this fork if you’re interested - GitHub - OpenSource-THG/security-kibana-plugin

1 Like

Thanks for the update, I appreciate it!
I’ll check out the link.