# OpenID Connect stand-alone Elastic with Keycloak

**URL:** <https://discuss.elastic.co/t/openid-connect-stand-alone-elastic-with-keycloak/322287>\
**Category:** Elasticsearch\
**Tags:** elastic-stack-security\
**Created:** [January 2, 2023, 7:28am UTC](https://discuss.elastic.co/t/openid-connect-stand-alone-elastic-with-keycloak/322287 "2023-01-02T07:28:02Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![devbot](https://avatars.discourse-cdn.com/v4/letter/d/9de0a6/32.png) [@devbot](https://discuss.elastic.co/u/devbot)\
**Post date:** [January 2, 2023, 7:28am UTC](https://discuss.elastic.co/t/openid-connect-stand-alone-elastic-with-keycloak/322287/1 "2023-01-02T07:28:02Z")

</div>

I would like to have a single node ES (no Kibana involved) authenticate against Keycloak for all requests.

I've followed the [OpenID Connect without Kibana](https://www.elastic.co/guide/en/elasticsearch/reference/current/oidc-guide.html#oidc-without-kibana) documentation to the best of my knowledge. However, this and the openID documentation on ES revolves around a redirect uri and external web app. I'm stuck on this because the intention here is to have, among other things, back-end code authenticate against Keycloak as a requirement for hitting ES (with no web apps involved).

My docker-compose file:

```auto
version: "2.2"

services:
  setup:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    volumes:
      - certs:/usr/share/elasticsearch/config/certs
    user: "0"
    command: >
      bash -c '
        if [x${ELASTIC_PASSWORD} == x]; then
          echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
          exit 1;
        elif [x${KIBANA_PASSWORD} == x]; then
          echo "Set the KIBANA_PASSWORD environment variable in the .env file";
          exit 1;
        fi;
        if [! -f config/certs/ca.zip]; then
          echo "Creating CA";
          bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
          unzip config/certs/ca.zip -d config/certs;
        fi;
        if [! -f config/certs/certs.zip]; then
          echo "Creating certs";
          echo -ne \
          "instances:\n"\
          " - name: es01\n"\
          " dns:\n"\
          " - es01\n"\
          " - localhost\n"\
          " ip:\n"\
          " - 127.0.0.1\n"\
          > config/certs/instances.yml;
          bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
          unzip config/certs/certs.zip -d config/certs;
        fi;
        echo "Setting file permissions"
        chown -R root:root config/certs;
        find . -type d -exec chmod 750 \{\} \;;
        find . -type f -exec chmod 640 \{\} \;;
        echo "Waiting for Elasticsearch availability";
        until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
        echo "Setting kibana_system password";
        until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
        echo "All done!";
      '
    healthcheck:
      test: ["CMD-SHELL", "[-f config/certs/es01/es01.crt]"]
      interval: 1s
      timeout: 5s
      retries: 120

  es01:
    depends_on:
      setup:
        condition: service_healthy
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    volumes:
      - certs:/usr/share/elasticsearch/config/certs
      - esdata01:/usr/share/elasticsearch/data
      - type: bind
        source: ./elasticsearch.yml
        target: /usr/share/elasticsearch/config/elasticsearch.yml
        read_only: true
      - type: bind
        source: ./certs.json
        target: /usr/share/elasticsearch/config/certs.json
        read_only: true
    ports:
      - ${ES_PORT}:9200
    environment:
      - node.name=es01
      - cluster.name=${CLUSTER_NAME}
      - cluster.initial_master_nodes=es01
      # - cluster.initial_master_nodes=es01,es02,es03
      # - discovery.seed_hosts=es02,es03
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/es01/es01.key
      - xpack.security.http.ssl.certificate=certs/es01/es01.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.http.ssl.verification_mode=certificate
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/es01/es01.key
      - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=${LICENSE}
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

volumes:
  certs:
    driver: local
  esdata01:
    driver: local

```

.env

```auto
# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=password

# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=password

# Version of Elastic products
STACK_VERSION=8.5.3

# Set the cluster name
CLUSTER_NAME=docker-cluster

# Set to 'basic' or 'trial' to automatically start the 30-day trial
# LICENSE=basic
LICENSE=trial

# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200
#ES_PORT=127.0.0.1:9200

# Port to expose Kibana to the host
KIBANA_PORT=5601
#KIBANA_PORT=80

# Increase or decrease based on the available host memory (in bytes)
MEM_LIMIT=1073741824

# Project namespace (defaults to the current folder name if not set)
#COMPOSE_PROJECT_NAME=myproject

```

Elasticsearch.yml

```auto
cluster.name: "docker-cluster"
network.host: 0.0.0.0

# xpack.security.authc.token.enabled: true
# xpack.security.authc.realms.oidc.oidc1:
# order: 2
# rp.client_id: "elasticsearch"
# rp.response_type: code
# rp.redirect_uri: "https://127.0.0.1:9200"
# op.issuer: "http://localhost:8080/auth/realms/Elastic"
# op.authorization_endpoint: "http://localhost:8080/auth/realms/Elastic/protocol/openid-connect/auth"
# op.token_endpoint: "http://localhost:8080/auth/realms/Elastic/protocol/openid-connect/token"
# op.jwkset_path: "certs.json"
# op.userinfo_endpoint: "http://localhost:8080/auth/realms/Elastic/protocol/openid-connect/userinfo"
# op.endsession_endpoint: "http://localhost:8080/auth/realms/Elastic/protocol/openid-connect/logout"
# rp.post_logout_redirect_uri: "https://127.0.0.1:9200/"
# claims.principal: preferred_username

```

My keycloak instance is running at [http://localhost:8080](http://localhost:8080)  
with a realm "Elastic" and client "elasticsearch"

So far my process is:

- run `docker-compose up -d`

- Inside the elasticsearch container:

- Restart ES container

Then, following the [OpenID Connect without Kibana](https://www.elastic.co/guide/en/elasticsearch/reference/current/oidc-guide.html#oidc-without-kibana) steps, I:

- Create the facilitator role and "facilitator" user in ES as per the [Service Account user for accessing the APIs](https://www.elastic.co/guide/en/elasticsearch/reference/8.5/oidc-guide.html#_service_account_user_for_accessing_the_apis)

- Execute Step 1 of [Handling the Authentication Flow section](https://www.elastic.co/guide/en/elasticsearch/reference/8.5/oidc-guide.html#_handling_the_authentication_flow) which returns a response example:

```auto
{
	"redirect": "http://localhost:8080/auth/realms/Elastic/protocol/openid-connect/auth?response_type=code&redirect_uri=https%3A%2F%2F127.0.0.1%3A9200&state=Hw-RDYrwwFFUYw_9fGFYWsXyWEReCjlkdIMfKz2uBYY&nonce=jerbpKm5n2i48OGS-z5H47oTXcEL33bSOKSrfRlPQGY&client_id=elasticsearch&scope=openid",
	"state": "Hw-RDYrwwFFUYw_9fGFYWsXyWEReCjlkdIMfKz2uBYY",
	"nonce": "jerbpKm5n2i48OGS-z5H47oTXcEL33bSOKSrfRlPQGY",
	"realm": "oidc1"
}

```

This is where I am unsure on how to proceed with the Authentication flow. In my elasticsearch.yml I don't know what to put as rp.redirect\_uri and rp.post\_logout\_redirect\_uri (my ES endpoint is just a filler/guess) given that there is no other web app involved. I'm sure it makes the redirect url returned invalid right now because keycloak gives a 400 error to it.

---

<div class="post-metadata">

**Author:** ![TimV](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/timv/32/13162_2.png) [@TimV](https://discuss.elastic.co/u/TimV)\
**Post date:** [January 3, 2023, 3:36am UTC](https://discuss.elastic.co/t/openid-connect-stand-alone-elastic-with-keycloak/322287/2 "2023-01-03T03:36:52Z")

</div>

> [@devbot](#):
>
> I'm stuck on this because the intention here is to have, among other things, back-end code authenticate against Keycloak as a requirement for hitting ES (with no web apps involved

That is not something that OpenID Connect can do. It is explicitly a protocol for logging into a _client_ that can handle flows, it isn't just a backend for username/password (and can't be used that way).

From the [official OpenID Connect page](https://openid.net/connect/):

> It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

If you don't have an OIDC aware client (e.g. a webapp, or a native client), you can't use OIDC. There is nothing in OIDC that allows an API server like Elasticsearch to authenticate REST requests via OIDC.

* * *

_(OK, technically I lied, it is possible to hack something together via the [OIDC implicit flow](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowSteps), but it's an abuse of OIDC, and Elasticsearch doesn't currently support it, nor do we have plans to do so)_

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [January 31, 2023, 3:37am UTC](https://discuss.elastic.co/t/openid-connect-stand-alone-elastic-with-keycloak/322287/3 "2023-01-31T03:37:29Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
