Integrations · OIDC
Kibana / OpenSearch SSO
Configure OIDC SSO for Kibana (Elasticsearch) and OpenSearch Dashboards using Clavex. Covers both the Elastic stack (8.x) and the OpenSearch community fork. Role mapping from Clavex group or realm_access claims is included.
License note: OIDC SSO for Kibana requires an Elastic Platinum
or higher license. For the open-source alternative, use OpenSearch with the Security plugin
(free). Both configurations are covered below.
Prerequisites
- Elasticsearch + Kibana ≥ 8.0 (Platinum/Enterprise) or OpenSearch ≥ 2.0
- TLS enabled on Elasticsearch/OpenSearch
- Clavex at
https://id.acme.eu, org slugacme
Step 1 — Register OIDC Client in Clavex
$ curl -X POST https://id.acme.eu/api/v1/organizations/acme/clients \
-H 'Authorization: Bearer $ADMIN_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"client_id": "kibana",
"client_name": "Kibana",
"grant_types": ["authorization_code", "refresh_token"],
"redirect_uris": ["https://kibana.acme.eu/api/security/oidc/callback"],
"scopes": ["openid", "profile", "email", "groups"],
"token_endpoint_auth_method": "client_secret_post"
}'
Step 2a — Elastic Stack (Kibana 8.x)
elasticsearch.yml
xpack.security.authc.realms.oidc.clavex:
order: 1
rp.client_id: "kibana"
rp.response_type: "code"
rp.redirect_uri: "https://kibana.acme.eu/api/security/oidc/callback"
rp.requested_scopes: ["openid", "profile", "email", "groups"]
op.issuer: "https://id.acme.eu/acme"
op.authorization_endpoint: "https://id.acme.eu/acme/authorize"
op.token_endpoint: "https://id.acme.eu/acme/token"
op.userinfo_endpoint: "https://id.acme.eu/acme/userinfo"
op.jwkset_path: "https://id.acme.eu/acme/jwks"
claims.principal: "email"
claims.groups: "groups"
$ elasticsearch-keystore add xpack.security.authc.realms.oidc.clavex.rp.client_secret
Enter value for xpack.security.authc.realms.oidc.clavex.rp.client_secret: cs_xxxxxxxxxxxxxxxx
kibana.yml
xpack.security.authc.providers:
oidc.clavex:
order: 0
realm: "clavex"
description: "Sign in with Clavex"
icon: "https://id.acme.eu/logos/clavex.svg"
hint: "SSO via corporate identity"
basic.basic:
order: 1
Role mapping (elasticsearch)
$ curl -u elastic:$ES_PASS -X PUT \
https://elasticsearch.acme.eu:9200/_security/role_mapping/clavex-admins \
-H 'Content-Type: application/json' \
-d '{
"roles": ["kibana_admin", "monitoring_user"],
"rules": {
"field": { "groups": "kibana-admins" }
},
"enabled": true
}'
Step 2b — OpenSearch Dashboards
Edit opensearch_dashboards.yml:
opensearch_security.auth.type: "openid"
opensearch_security.openid.connect_url: "https://id.acme.eu/acme/.well-known/openid-configuration"
opensearch_security.openid.client_id: "kibana"
opensearch_security.openid.client_secret: "cs_xxxxxxxxxxxxxxxx"
opensearch_security.openid.scope: "openid profile email groups"
opensearch_security.openid.base_redirect_url: "https://dashboards.acme.eu"
opensearch_security.openid.trust_dynamic_headers: false
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Unable to perform OIDC authentication |
Client secret not in keystore or wrong | Re-add with elasticsearch-keystore add; restart Elasticsearch |
| Users have no role after login | Role mapping missing or groups claim not populated | Verify role mapping via GET /_security/role_mapping; check groups claim in token |
| Redirect loop between Kibana and Clavex | Kibana session cookie not set (domain/protocol mismatch) | Ensure server.publicBaseUrl in kibana.yml matches the browser URL exactly |
| JWK set fetch fails | Elasticsearch can't reach Clavex JWKS URL | Use op.jwkset_path with a local file path as fallback: download JWKS and point to file |