RoR entreprise, OIDC and custom claims: possible?

Hello!
ReadOnlyRest entreprise user here, I’m stuck with a problem I’m unable to solve.

What I try to achieve:
Perform Authentication for kibana against OIDC identity provider(in my case keycloak) AND use custom claim in access token to fetch allowed indices .

What I’ve tried so far:

  • Use oidc support from Ror enterprise to perform authentication : authentication works but I’ve found no solution to grab custom claims from the access token so I was unable to filter out index access.

  • Add an authentication reverse proxy and forward the access token in Authorization header, then use jwt authentication from Ror.: Authentication and index access filtering works… as long as the first access token is valid. As soon as the access token expires, even though the reverse proxy refreshes it, it seems to not be taken by RoR unless the user goes manually back to /login, which effectively renders this solution useless(especially with an access token expiry set to 5 mn)

After this long situation overview, here comes the questions:

  • Is my hypothesis correct regarding RoR processing Authorization header only on /login page?
  • Is there any solution to use the Oidc support from Ror while fetching data from a claim of the access token?

Hello @pchesneau, the scenario is very clearly described, thank you.

Directly to your questions:

  1. The credentials presented in login phase (including the JWT header coming from the auth proxy) is saved in the session object for the whole Kibana session. While on the Elasticsearch side, the credentials are validated on a per-request basis. This is a JWT specific issue (as a form of credentials which is able to expire) ROR Enterprise needs to handle specifically.

  2. Will look into the OIDC issue where the claims are not forwarded and report back.

Thanks a lot @sscarduzio for this lightning fast answer !
As a quick workaround I’ll increase the validity of access token used by kibana.
I’m looking forward to hearing from you about OIDC and custom claims :slight_smile:.
If you have any ideas to test about this, please let me know !

The other solution I’ve in mind is to configure the reverse proxy to extract claims from the access token and set them in custom headers, then use header authentication from RoR. However this solution is not really elegant.

Both are very good ideas as workarounds indeed.

@pchesneau could you share this log line if you have it? It should appear with ROR in debug mode

        logger.debug("OIDC obtained raw profile: " + JSON.stringify(profile))

Hello @sscarduzio
I’m trying to fetch this for you, however since my last try I’ve migrated to openshift, and it seems that enabling OIDC is not possible when Kibana+RoR is in openshift. I’m unable to correctly set the OIDC callbackURL (it seems to be inferred from the kibana server.host config which, in docker container must be set to “0.0.0.0”)

{"type":"log","@timestamp":"2020-12-18T09:54:36Z","tags":["info","readonlyrest_kbn:OIDCExpressServer"],"pid":8,"message":"OIDC Settings \n{\n  \"buttonName\": \"KeyCloak OpenID\",\n  \"type\": \"oidc\",\n  \"issuer\": \"https://keycloak-infratools-qualif-multi.<redacted>/auth/realms/<redacted>/\",\n   \"authorizationURL\": \"https://keycloak-infratools-qualif-multi.<redacted>/auth/realms/<redacted>/protocol/openid-connect/auth\",\n   \"tokenURL\": \"https://keycloak-infratools-qualif-multi.<redacted>/auth/realms/<redacted>/protocol/openid-connect/token\",\n   \"userInfoURL\": \"https://keycloak-infratools-qualif-multi.<redacted>/auth/realms/<redacted>/protocol/openid-connect/userinfo\",\n   \"clientID\": \"kibana.infra.<redacted>\",\n  \"clientSecret\": \"<redacted>\",\n  \"scope\": \"openid email profile\",\n  \"usernameParameter\": \"preferred_username\",\n  \"groupsParameter\": \"groups\",\n  \"kibanaExternalHost\": \"https://kibana-direct-infratools-qualif-multi.<redacted>\",\n   \"protocol\": \"https\",\n  \"logoutUrl\": \"https://keycloak-infratools-qualif-multi.<redacted>/auth/realms/<redacted>/protocol/openid-connect/logout\",\n   \"callbackURL\": \"http://0.0.0.0:5601/ror_kbn_sso_oidc_kc/callback\",\n   \"routePrefix\": \"/ror_kbn_sso_oidc_kc\",\n  \"name\": \"oidc_kc\"\n}"}

As a last chance I’ve tried to add the property “callbackURL” in the OIDC config, but to no avail.

I’ll try on my old platform (VM based) to get this log for you but it seems that I won’t be able to deploy it on openshift.

1 Like

Another excellent feedback about the necessity of “callbackURL” under certain deployment conditions. Will add this too.

Hi @pchesneau I have a fix for you, please send me a direct message in this forum with your ROR and Kibana version. I will provide you with a build.

1 Like

Hello @sscarduzio I’m unable to respond through direct message (I got an error message) . So here are the required informations: kibana/kibana-oss:7.8.1 + pluginVersion=1.25.0

(on a side note: I’m not the registered user of the plugin; It’s a colleague of mine. If you need some proof of our licensing, just let me know :))

Hi Pierre,

Maybe I had to initiate the private conversation on your behalf, for some anti spam setting.

Please can somebody with an Enterprise download authorized email address contact me on support@readonlyrest.com?

Hello ! Sure!
I’ve asked my collegue Christophe to send you an email :slight_smile: . It should be in your mailbox soon !

Hello @sscarduzio!

I would like to thank you very much for all the help you’ve offered to me through private message.
I have created 2 PR on the documentation with information that missed me during configuration.

Also, If anyone needs to use an OIDC provider only accessible through a proxy, here is my solution

Configure the oidc connector as follow:

readonlyrest_kbn.auth:
  signature_key: "${KIBANA_SIGNATURE}"
  oidc_kc: 
    buttonName: "OIDC Keycloak"
    type: "oidc"
    issuer: "https://${KEYCLOAK_BASE_URL}/<...>"
    authorizationURL: "https://${KEYCLOAK_BASE_URL}/<...>"
    tokenURL: 'http://127.0.0.1:8083/<...>'
    userInfoURL: 'http://127.0.0.1:8083/<...>'
    clientID: "${KIBANA_CLIENT_ID}"
    clientSecret: "${KIBANA_CLIENT_SECRET}"
    scope: 'openid email profile'
    usernameParameter: 'name'
    groupsParameter: "kibana_roles"
    protocol: 'https'
    kibanaExternalHost: '$YOUR_EXTERNAL_HOST'
    logoutUrl: "https://${KEYCLOAK_BASE_URL}/<...>"

Then,on an accessible host, configure http_proxy and https_proxy, then start a traefik reverse proxy with the following configuration :
traefik.yml:

entryPoints:
  web:
    address: ":8083"
providers:
  file:
    filename: "/etc/traefik/dynamic.yml"

/etc/traefik/dynamic.yml

http:
  middlewares:
    addHostHeaders:
      headers:
        accessControlAllowHeaders: 
          - Authorization
        accessControlAllowCredentials: true
        customRequestHeaders:
         Host: '{{env "KEYCLOAK_BASE_URL"}}' 
  routers:
    Router-1:
      # By default, routers listen to every entry po
      rule: "Host(`127.0.0.1`)"
      middlewares: ["addHostHeaders"]
      service: "service-1"
  services:
    service-1:
      loadBalancer:
        servers:
          - url: https://{{env "KEYCLOAK_BASE_URL"}}

It can be on the same host as kibana, in a sidecar…

Thanks to you for the great contribution! Will accept the PRs.

1 Like