Unable to configure Operate to work with generic OIDC auth provider in docker-compose

Hi. A am using latest Camunda 8.6 self managed with docker compose locally. I am trying to make it wrk with my custom OIDC provider. Curretly docs are not clear enough about it. I’ve found this thread: Custom OIDC Provider configuration with self hosted service (with docker compose) and was able to make progress: I’ve setup Identity to work with my custom provider successfully (from here Connect to an OpenID Connect provider | Camunda 8 Docs). But I have a problem with Operate. It is configured according to this doc: Connect to an OpenID Connect provider | Camunda 8 Docs. But setting here are marked as deprecated with a link to docs, that are related to Identity, not Operate. Even with these deprecated settings Operate tries to connect to my OIDC provider, but fails, because it uses Keycloak’s URLs, while I have different auth/keys/token/etc paths. For example Operate redirects to “<issuer_url>/protocol/openid-connect/auth” for athentication, tries to get token from “<issuer_url>/protocol/openid-connect/token” and keys from “<issuer_url>/protocol/openid-connect/certs”.
My current Operate env vars:

      - CAMUNDA_OPERATE_ZEEBE_GATEWAYADDRESS=zeebe:26500
      - CAMUNDA_OPERATE_ELASTICSEARCH_URL=http://elasticsearch:9200
      - CAMUNDA_OPERATE_ZEEBEELASTICSEARCH_URL=http://elasticsearch:9200
      - CAMUNDA_OPERATE_MULTITENANCY_ENABLED=false
      # zeebe api auth settings
      - ZEEBE_CLIENT_ID=zeebe
      - ZEEBE_CLIENT_SECRET=zecret
      - ZEEBE_TOKEN_AUDIENCE=zeebe-api
      - ZEEBE_AUTHORIZATION_SERVER_URL=http://host.docker.internal:3007/oauth/token
      - ZEEBE_CLIENT_CONFIG_PATH=/tmp/zeebe_auth_cache
      # https://docs.camunda.io/docs/self-managed/operate-deployment/operate-authentication/?authentication=identity#enable-identity
      - SPRING_PROFILES_ACTIVE=identity-auth
      - CAMUNDA_OPERATE_IDENTITY_BASEURL=http://identity:8084
      - CAMUNDA_OPERATE_IDENTITY_ISSUER_URL=http://localhost:3007
      - CAMUNDA_OPERATE_IDENTITY_ISSUER_BACKEND_URL=http://host.docker.internal:3007
      - CAMUNDA_OPERATE_IDENTITY_CLIENTID=operate
      - CAMUNDA_OPERATE_IDENTITY_CLIENTSECRET=XALaRPl5qwTEItdwCMiPS62nVpKs7dL7
      - CAMUNDA_OPERATE_IDENTITY_AUDIENCE=operate-api
      - CAMUNDA_OPERATE_IDENTITY_RESOURCEPERMISSIONSENABLED=false
      - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://host.docker.internal:3007
      - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI=http://host.docker.internal:3007/oauth/discovery/keys
      # motitoring
      - management.endpoint.health.probes.enabled=true

How should I reconfigre it to work properly with my custom OIDC provider via Identity?

Hi @d.arkhipov, welcome to the forums! The first thing I noticed was the active Spring profile appears to be incorrect. Try setting SPRING_PROFILES_ACTIVE=oidc in your config (see environment variables here).

Hi. I already tried it: when I set Spring profile to “oidc” - Operate does not use OAUTH at all, it just redirects to a built-in login page and uses it’s internal database user. May be some other configuration options are also required?

In Operate logs I then see that it is using these profiles: operate, standalone, auth, oidc

@d.arkhipov - apologies, the “oidc” profile is for Identity, not Operate. Operate should be using “identity-auth” as you had it originally.

I believe you need to add a redirect URL: CAMUNDA_OPERATE_IDENTITY_REDIRECT_ROOT_URL

The docs say you need to add it (reference) but don’t give the environment variable name; I’ll raise an issue with the docs team.

This var sets the OAUTH redirect root URL, so it is the URL of Operate, used by authorization server to redirect user after successfull authentication back to Operate. But I need to configure Operate to redirect to correct authorization endpoint of my OIDC provider. Currently when I try to login to Operate - it redirects me to http://localhost:3007/protocol/openid-connect/auth, which is the endpoit used by Keycloak, but I have auth endpoint at http://localhost:3007/oauth/authorize. Also the same problem with token endpoint and certs endpoint

Does Operate support automatic OICD configuration discovery (/.well-known/openid-configuration)?

@d.arkhipov - I don’t think it supports configuration discovery at this time, but that is good feedback for the team.

I know I’ve missed twice already :sweat_smile: but I think it is something with the redirect URLs. The next one to look at is the CAMUNDA_OPERATE_IDENTITY_ISSUER_URL. If you look in the documentation, the example value for that includes a path. Perhaps try setting that to http://localhost:3007/oauth/authorize?

That doesn’t solve my issue. Examples include path just because they are based on Keycloak paths. Keycloak has realms feature, so base URL includes hostname and path to realm as well. So this is considered a “base URL”. In my case base URL does not have a path part, just a hostname. If I set issuer URL as you advice - Operate redirects me to http://localhost:3007/oauth/authorize/protocol/openid-connect/auth. So /protocol/openid-connect/auth part seem to be hardcoded in Operate? If there is no way to configure it - then Operate does not seem to support a generic OIDC provider, bacause enpoints may differ depending on used provider software.

Hi. I made some experiments and found out, that with current Operate setup it is stick to Keycloak and even does not need Identity to work (at least without resource permissions enabled). So what does Operate do now:

  1. Uses Keycloak authorization (to redirect user to login page), token (to get access token after login) and certificates (to validate access JWT) URLs. On custom OIDC those URLs may differ, and in that case authentication won’t work. I made additional URLs on my OIDC provider so that it responds the same as Keycloak now. And after that I was able to authenticate successfully in Operate.
  2. Expects “permissions” claim to be present inside JWT. Without it Operate shows “No permissions for Operate” message after successfull login. I added that claim to generated JWT and then was able to sucessfully authorize in Operate.

To sum up, I had to make so hacks to my OIDC to make Operate work. In fact, I disguised it as Keycloak. In that setup I even do not need Identity, because Operate does not address it at all (at least without resource permissions enabled).

What would I expect from Operate to support custom OIDC:

  1. Have some configuration variables to change OIDC authorise/token/certs URLs. Or have an option to make Operate retrieve those URLs from Identity, because Identity already knows them (via OIDC configuration discovery).
  2. Identity has claim mapping functionality. So that it is possible to map token claims to roles/permissions, required by Operate/Optimize/etc. So there should be an option to make Operate use that mappings instead of “permissions” claim in JWT. Or docs should be modified to include instructions what claims must be present in JWT to make Operate authorization work as expected.

To sum up, is there something like “CAMUNDA_OPERATE_IDENTITY_TYPE=GENERIC” that would make Operate address Idetity in both cases?

But generally I don’t like an idea to use Identity with a custom OIDC provider / IAM service. I would better improve Operate (and other services) to support OIDC configuration discovery and make docs what claims must be present in JWT form permission system to work properly. Additional claims are usually easily configurable.

Hi @d.arkhipov,

I have a running cluster using Keycloak as OIDC provider, installed by Helm charts in Kubernetes.

These are the configuration snippets generated by Helm for Operate:

  CAMUNDA_IDENTITY_BASEURL: "http://camunda-identity:80"
  CAMUNDA_IDENTITY_TYPE: "GENERIC"
  CAMUNDA_IDENTITY_ISSUER: "http://keycloak:8090/realms/ingo-keycloak-as-oidc"
  CAMUNDA_IDENTITY_ISSUER_BACKEND_URL: "http://keycloak:8090/realms/ingo-keycloak-as-oidc"
data:
  application.yaml: |
    spring:
      profiles:
        active: "identity-auth"
      security:
        oauth2:
          resourceserver:
            jwt:
              issuer-uri: "http://keycloak:8090/realms/ingo-keycloak-as-oidc"
              jwk-set-uri: "http://keycloak:8090/realms/ingo-keycloak-as-oidc/protocol/openid-connect/certs"

    camunda:
      identity:
        clientId: "camunda-operate"
        audience: "camunda-operate"
          env:
            - name: CAMUNDA_LICENSE_KEY
              valueFrom:
                secretKeyRef:
                  name: camunda-license
                  key: key
            - name: CAMUNDA_IDENTITY_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: camunda-operate-identity-secret
                  key: operate-secret
            - name: ZEEBE_CLIENT_ID
              value: "camunda-zeebe"
            - name: ZEEBE_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: camunda-zeebe-identity-secret
                  key: zeebe-secret
            - name: ZEEBE_AUTHORIZATION_SERVER_URL
              value: "http://keycloak:8090/realms/ingo-keycloak-as-oidc/protocol/openid-connect/token"
            - name: ZEEBE_TOKEN_AUDIENCE
              value: "camunda-zeebe"
            - name: ZEEBE_CLIENT_CONFIG_PATH
              value: /tmp/zeebe_auth_cache
            # the host name of Operate that is used when connecting with the Zeebe cluster
            # via atomix-cluster (SWIM)
            - name: ZEEBE_GATEWAY_CLUSTER_HOST
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: status.podIP
            # the unique member id (in this case the pod name) that is used as identifier inside the SWIM cluster
            - name: ZEEBE_GATEWAY_CLUSTER_MEMBERID
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.name
            # the name of the atomix cluster (SWIM) to connect to (must be the same as for the Zeebe cluster)
            - name: ZEEBE_GATEWAY_CLUSTER_CLUSTERNAME
              value: camunda-zeebe
            # the port the service expects requests/messages from the atomix cluster (must be exposed internally)
            - name: ZEEBE_GATEWAY_CLUSTER_PORT
              value: "26502"
            # the initial contact point to join the SWIM (atomix) cluster
            - name: ZEEBE_GATEWAY_CLUSTER_INITIALCONTACTPOINTS
              value: camunda-zeebe:26502
            - name: CAMUNDA_IDENTITY_AUTH_SCOPES
              value: openid profile email

Operate, along with Tasklist, uses the identity-sdk to encapsulate the authentication.

Hope this helps, Ingo