Keycloak oidc Elastisearch Error

Hello team,

we want to use keycloak as an identity provider for kibana and elasticsearch.
We managed to hit a blocker. We have an error in the elasticsearch log.

java.lang.IllegalStateException: security initialization failed
Likely root cause: java.text.ParseException: Missing required "keys" member
        at com.nimbusds.jose.jwk.JWKSet.parse(JWKSet.java:371)
        at com.nimbusds.jose.jwk.JWKSet.parse(JWKSet.java:350)
        at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator.readJwkSetFromFile(OpenIdConnectAuthenticator.java:326)
        at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator.createIdTokenValidator(OpenIdConnectAuthenticator.java:647)
        at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator.<init>(OpenIdConnectAuthenticator.java:150)
        at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm.<init>(OpenIdConnectRealm.java:120)
        at org.elasticsearch.xpack.security.authc.InternalRealms.lambda$getFactories$7(InternalRealms.java:120)
        at org.elasticsearch.xpack.security.authc.Realms.initRealms(Realms.java:223)
        at org.elasticsearch.xpack.security.authc.Realms.<init>(Realms.java:78)
        at org.elasticsearch.xpack.security.Security.createComponents(Security.java:519)
        at org.elasticsearch.xpack.security.Security.createComponents(Security.java:443)
        at org.elasticsearch.node.Node.lambda$new$18(Node.java:605)
        at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at org.elasticsearch.node.Node.<init>(Node.java:609)
        at org.elasticsearch.node.Node.<init>(Node.java:278)
        at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:217)
        at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:217)
        at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:397)
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159)
        at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150)
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:75)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:116)
        at org.elasticsearch.cli.Command.main(Command.java:79)
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115)

From this error, I understand that the jwsset.json from /.well-known/openid-configuration is incomplete. And Elastisearch needs more data.

Do you know what I am missing in the keycloak config?

Thanks!

If you can give us more information about your setup, maybe we could try to reproduce it and help you debug. Keycloak’s /.well-known/openid-configuration specifies a jwks_uri. The top-level entry in that hash is keys, which is what I’m assuming what the library is looking for. It may be as simple as specifying/overridding the jwks_uri in your configuration?

this is the anonimezed json from /.well-known/openid-configuration and jwks_uri has {“keys”:[{“kid”:" .

{
    "issuer":"https://auth.xxxx/auth/realms/kibana",
    "authorization_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/auth",
    "token_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/token",
    "introspection_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/token/introspect",
    "userinfo_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/userinfo",
    "end_session_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/logout",
    "jwks_uri":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/certs",
    "check_session_iframe":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/login-status-iframe.html",
    "grant_types_supported":[
       "authorization_code",
       "implicit",
       "refresh_token",
       "password",
       "client_credentials",
       "urn:ietf:params:oauth:grant-type:device_code",
       "urn:openid:params:grant-type:ciba"
    ],
    "response_types_supported":[
       "code",
       "none",
       "id_token",
       "token",
       "id_token token",
       "code id_token",
       "code token",
       "code id_token token"
    ],
    "subject_types_supported":[
       "public",
       "pairwise"
    ],
    "id_token_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512"
    ],
    "id_token_encryption_alg_values_supported":[
       "RSA-OAEP",
       "RSA-OAEP-256",
       "RSA1_5"
    ],
    "id_token_encryption_enc_values_supported":[
       "A256GCM",
       "A192GCM",
       "A128GCM",
       "A128CBC-HS256",
       "A192CBC-HS384",
       "A256CBC-HS512"
    ],
    "userinfo_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512",
       "none"
    ],
    "request_object_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512",
       "none"
    ],
    "response_modes_supported":[
       "query",
       "fragment",
       "form_post"
    ],
    "registration_endpoint":"https://auth.xxxx/auth/realms/kibana/clients-registrations/openid-connect",
    "token_endpoint_auth_methods_supported":[
       "private_key_jwt",
       "client_secret_basic",
       "client_secret_post",
       "tls_client_auth",
       "client_secret_jwt"
    ],
    "token_endpoint_auth_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512"
    ],
    "introspection_endpoint_auth_methods_supported":[
       "private_key_jwt",
       "client_secret_basic",
       "client_secret_post",
       "tls_client_auth",
       "client_secret_jwt"
    ],
    "introspection_endpoint_auth_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512"
    ],
    "claims_supported":[
       "aud",
       "sub",
       "iss",
       "auth_time",
       "name",
       "given_name",
       "family_name",
       "preferred_username",
       "email",
       "acr"
    ],
    "claim_types_supported":[
       "normal"
    ],
    "claims_parameter_supported":true,
    "scopes_supported":[
       "openid",
       "address",
       "groups",
       "microprofile-jwt",
       "email",
       "phone",
       "web-origins",
       "roles",
       "offline_access",
       "member",
       "profile"
    ],
    "request_parameter_supported":true,
    "request_uri_parameter_supported":true,
    "require_request_uri_registration":true,
    "code_challenge_methods_supported":[
       "plain",
       "S256"
    ],
    "tls_client_certificate_bound_access_tokens":true,
    "revocation_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/revoke",
    "revocation_endpoint_auth_methods_supported":[
       "private_key_jwt",
       "client_secret_basic",
       "client_secret_post",
       "tls_client_auth",
       "client_secret_jwt"
    ],
    "revocation_endpoint_auth_signing_alg_values_supported":[
       "PS384",
       "ES384",
       "RS384",
       "HS256",
       "HS512",
       "ES256",
       "RS256",
       "HS384",
       "ES512",
       "PS256",
       "PS512",
       "RS512"
    ],
    "backchannel_logout_supported":true,
    "backchannel_logout_session_supported":true,
    "device_authorization_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/auth/device",
    "backchannel_token_delivery_modes_supported":[
       "poll"
    ],
    "backchannel_authentication_endpoint":"https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/ext/ciba/auth"
 }

To make a resume of my config. I have a realm kibana with an oidc client that is supposed to connect to elasticsearch. I have attached screenshots of my config. Do you need additional information?

Client Scopes

Mappers, I have added all, because I believed that this was the source of my error…

And I have full scope allowed turned on.

Do you need any additional info ?

Thanks!

Thanks for posting the Keycloak config. Can you also post your Kibana/ES config? Since the error is coming from that client, it would be useful to see how you have configured it there.

Hello,

Thanks for answering so fast. This is my elastic and kibana config`s

Elasticsearch.yml

xpack.security.authc.realms.oidc.kibana:
  order: 2
  rp.client_id: "roc3-kibana-oidc"
  rp.response_type: code
  rp.redirect_uri: "https://xxx:5601/api/security/oidc/callback"
  op.issuer: "https://auth.xxxx/auth/realms/kibana"
  op.authorization_endpoint: "https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/auth"
  op.token_endpoint: "https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/token"
  op.jwkset_path: "https://auth.xxxx/auth/realms/Kibana/.well-known/openid-configuration"
  #op.jwkset_path: "oidc/jwkset.json"
  op.userinfo_endpoint: "https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/userinfo"
  op.endsession_endpoint: "https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/logout"
  rp.post_logout_redirect_uri: "https://xxxx:5601/logout"
  claims.principal: sub
  claims.groups: groups

Kibana.yml

xpack.security.authc.providers:
  oidc.kibana:
    order: 0
    realm: kibana
    description: Log in with Keycloak user  
  basic.basic1:
    order: 1

Thanks!

Have you tried setting the op.jwkset_path to https://auth.xxxx/auth/realms/kibana/protocol/openid-connect/certs? From the ES docs, it looks like it’s asking for jwks_uri, not the .well-known endpoint.

1 Like

Thanks a lot!! It works now. Can you please send me the documentation where you read that? because what I have read everybody was putting .well-know/openid-conf.

Thanks!

This section of the Elasticsearch docs indicating it contains “a JSON Web Key Set with the key material that the OpenID Connect Provider uses for signing tokens and claims responses”:

op.jwkset_path

The path to a file or a URL containing a JSON Web Key Set with the key material that the OpenID Connect Provider uses for signing tokens and claims responses. If a path is set, it is resolved relative to the Elasticsearch config directory. Elasticsearch will automatically monitor this file for changes and will reload the configuration whenever it is updated. Your OpenID Connect Provider should provide you with this file or a URL where it is available.

and a few posts on the elastic forum indicating using the /certs url: