Getting 403 FORBIDDEN for optimize client callback

Hi, I am trying to configure Camunda 8 optimize with my external identity provider, the following configuration is working fine for opreate/tasklist/embeded identity/management identity, but for optimize, when trying to login I get redirected to idp login page, and after successful login I can see in optimize logs 403 forbidden:

optimize | 2026-02-10 07:29:22.608 DEBUG 8 — [nio-8090-exec-4] o.s.s.w.FilterChainProxy : Securing GET /
optimize | 2026-02-10 07:29:22.608 DEBUG 8 — [nio-8090-exec-4] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
optimize | 2026-02-10 07:29:22.609 DEBUG 8 — [nio-8090-exec-4] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using Ant [pattern=‘/api/‘]
optimize | 2026-02-10 07:29:22.609 DEBUG 8 — [nio-8090-exec-4] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using Ant [pattern=’/
’]
optimize | 2026-02-10 07:29:22.609 DEBUG 8 — [nio-8090-exec-4] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing io.camunda.optimize.rest.security.ccsm.CCSMSecurityConfigurerAdapter$$Lambda/0x00007f30b5a4d010@18024492
optimize | 2026-02-10 07:29:22.790 DEBUG 8 — [nio-8090-exec-2] o.s.s.w.FilterChainProxy : Securing GET /api/authentication/callback?code=5F72F309C80C4B1A0E90879E4A2B2F8C42DB53C3EA67F05CB4D3F0B92A232471-1&scope=openid%20profile%20offline_access%20camunda-api-scope&session_state=7BYxmluw7Suj7rDm5DUGvN4iCgvWIrb6xTWEwSATvh8.7B1205FE77B693E55B19C6CF1B569030&iss=https%3A%2F%2F10.14.8.61%3A8055
optimize | 2026-02-10 07:29:22.790 DEBUG 8 — [nio-8090-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
optimize | 2026-02-10 07:29:22.790 DEBUG 8 — [nio-8090-exec-2] o.s.s.w.FilterChainProxy : Secured GET /api/authentication/callback?code=5F72F309C80C4B1A0E90879E4A2B2F8C42DB53C3EA67F05CB4D3F0B92A232471-1&scope=openid%20profile%20offline_access%20camunda-api-scope&session_state=7BYxmluw7Suj7rDm5DUGvN4iCgvWIrb6xTWEwSATvh8.7B1205FE77B693E55B19C6CF1B569030&iss=https%3A%2F%2F10.14.8.61%3A8055
optimize | 2026-02-10 07:29:22.791 DEBUG 8 — [nio-8090-exec-2] o.s.w.s.DispatcherServlet : GET “/optimize/api/authentication/callback?code=5F72F309C80C4B1A0E90879E4A2B2F8C42DB53C3EA67F05CB4D3F0B92A232471-1&scope=openid%20profile%20offline_access%20camunda-api-scope&session_state=7BYxmluw7Suj7rDm5DUGvN4iCgvWIrb6xTWEwSATvh8.7B1205FE77B693E55B19C6CF1B569030&iss=https%3A%2F%2F10.14.8.61%3A8055”, parameters={masked}
optimize | 2026-02-10 07:29:22.791 DEBUG 8 — [nio-8090-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to io.camunda.optimize.rest.AuthenticationRestService#loginCallback(String, String, String, HttpServletRequest, HttpServletResponse)
optimize | 2026-02-10 07:29:23.083 DEBUG 8 — [nio-8090-exec-2] o.s.w.s.DispatcherServlet : Completed 403 FORBIDDEN

my docker file is:

services:
  orchestration:
    image: camunda/camunda:${CAMUNDA_VERSION}
    container_name: orchestration    
    ports:
      - "26500:26500"
      - "9600:9600"
      - "8088:8080"  
    environment:
      CAMUNDA_DATABASE_INDEX_NUMBER_OF_REPLICAS: 0   
      CAMUNDA_IDENTITY_BASEURL: http://identity:8084
      CAMUNDA_SECURITY_AUTHORIZATIONS_ENABLED: true
      CAMUNDA_SECURITY_AUTHENTICATION_METHOD: oidc
      CAMUNDA_SECURITY_AUTHENTICATION_UNPROTECTEDAPI: false
      CAMUNDA_SECURITY_INITIALIZATION_DEFAULTROLES_ADMIN_USERS_0: my-admin-user
      CAMUNDA_SECURITY_INITIALIZATION_DEFAULTROLES_ADMIN_GROUPS_0: my-admin-group
      CAMUNDA_SECURITY_INITIALIZATION_DEFAULTROLES_ADMIN_CLIENTS_0: zeepi-api-client
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_CLIENTID: camunda-web-client
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_CLIENTSECRET: camunda-web-client-secret
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_ISSUERURI: https://my-idp-server            
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_REDIRECTURI: http://orchestration.eng.ncgr.gov.sa/sso-callback
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_AUDIENCES: camunda-api-audience,zeebe-api-audience,camunda-web-client
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_SCOPE: openid,profile,offline_access,camunda-api-scope    
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_USERNAMECLAIM: preferred_username
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_CLIENTIDCLAIM: client_id
      CAMUNDA_SECURITY_AUTHENTICATION_OIDC_GROUPSCLAIM: role        
      JAVA_TOOL_OPTIONS: "-Xms512m -Xmx512m -Djavax.net.ssl.trustStore=/opt/certs/customTrustStore.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
    env_file:
      - path: .env
        required: true
    restart: unless-stopped
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "timeout 60s bash -c ':> /dev/tcp/127.0.0.1/9600' || exit 1",
        ]
      interval: 30s
      timeout: 60s
      retries: 5
      start_period: 30s
    volumes:
      - orchestration:/usr/local/zeebe/data
      - "./.orchestration/application.yaml:/usr/local/camunda/config/application.yaml"
      - "/app/camunda/customTrustStore.jks:/opt/certs/customTrustStore.jks:ro" 
    networks:
      - camunda-platform
    extra_hosts:
      - "host.docker.internal:host-gateway"
    depends_on:
      elasticsearch:
        condition: service_healthy

  connectors:
    image: camunda/connectors-bundle:${CAMUNDA_CONNECTORS_VERSION}
    container_name: connectors
    ports:
      - "8086:8080"
    environment:
      CAMUNDA_CLIENT_MODE: self-managed
      CAMUNDA_CLIENT_RESTADDRESS: http://orchestration:8080
      CAMUNDA_CLIENT_GRPCADDRESS: http://orchestration:26500
      CAMUNDA_CLIENT_AUTH_METHOD: oidc
      CAMUNDA_CLIENT_AUTH_TOKENURL: https://my-idp-server/connect/token
      CAMUNDA_CLIENT_AUTH_CLIENTID: zeepi-api-client
      CAMUNDA_CLIENT_AUTH_CLIENTSECRET: zeepi-api-client-secret
      JAVA_TOOL_OPTIONS: "-Djavax.net.ssl.trustStore=/opt/certs/customTrustStore.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
    env_file: connector-secrets.txt
    restart: unless-stopped
    healthcheck:
      test:
        ["CMD", "curl", "-f", "http://localhost:8080/actuator/health/readiness"]
      interval: 30s
      timeout: 60s
      retries: 5
      start_period: 30s
    volumes:
      - "/app/camunda/customTrustStore.jks:/opt/certs/customTrustStore.jks:ro"
    networks:
      - camunda-platform
    extra_hosts:
      - "host.docker.internal:host-gateway"
    depends_on:
      orchestration:
        condition: service_healthy

  optimize:
    image: camunda/optimize:${CAMUNDA_OPTIMIZE_VERSION}
    container_name: optimize
    ports:
      - "8083:8090"
    environment:
      LOGGING_LEVEL_ROOT: DEBUG
      LOGGING_LEVEL_IO_CAMUNDA: DEBUG
      LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY: DEBUG
      LOGGING_LEVEL_IO_CAMUNDA_IDENTITY_SDK: DEBUG
      LOGGING_LEVEL_IO_CAMUNDA_IDENTITY_SDK_IMPL_REST: DEBUG
      LOGGING_LEVEL_IO_CAMUNDA_IDENTITY_SDK_IMPL_REST_RESTCLIENT: DEBUG
      CAMUNDA_OPTIMIZE_CONTEXT_PATH: /optimize
      SERVER_FORWARD_HEADERS_STRATEGY: framework
      HOST: ${HOST}
      OPTIMIZE_ELASTICSEARCH_HOST: elasticsearch
      OPTIMIZE_ELASTICSEARCH_HTTP_PORT: "9200"
      CAMUNDA_IDENTITY_TYPE: GENERIC
      SPRING_PROFILES_ACTIVE: oidc 
      CAMUNDA_IDENTITY_ISSUER: https://my-idp-server
      CAMUNDA_IDENTITY_ISSUER_BACKEND_URL: https://my-idp-server  
      CAMUNDA_IDENTITY_CLIENT_ID: optimize-api-client
      CAMUNDA_IDENTITY_CLIENT_SECRET: optimize-api-client-secret
      CAMUNDA_IDENTITY_AUDIENCE: optimize-api
      CAMUNDA_IDENTITY_AUTH_SCOPES: openid profile offline_access optimize-api-client 
      CAMUNDA_OPTIMIZE_IDENTITY_AUDIENCE: optimize-api
      CAMUNDA_OPTIMIZE_IDENTITY_BASE_URL: http://identity:8084
      CAMUNDA_IDENTITY_BASEURL: http://identity:8084
      management.endpoints.web.exposure.include: health,configprops
      MANAGEMENT_ENDPOINT_CONFIGPROPS_SHOW_VALUES: ALWAYS
      management.endpoint.health.probes.enabled: "true"
      JAVA_TOOL_OPTIONS: "-Djavax.net.ssl.trustStore=/opt/certs/customTrustStore.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/api/readyz"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    volumes:
      - "/app/camunda/customTrustStore.jks:/opt/certs/customTrustStore.jks:ro"
      - "./.optimize/environment-config.yaml:/optimize/config/environment-config.yaml"
    restart: on-failure
    networks:
      - camunda-platform
    extra_hosts:
      - "host.docker.internal:host-gateway"
    depends_on:
      identity:
        condition: service_healthy
      elasticsearch:
        condition: service_healthy

  identity:
    container_name: identity
    image: camunda/identity:${CAMUNDA_IDENTITY_VERSION}
    ports:
      - "8084:8084"
    environment:
      #LOGGING_LEVEL_ROOT: DEBUG
      #LOGGING_LEVEL_IO_CAMUNDA: DEBUG
      #LOGGING_LEVEL_IO_CAMUNDA_IDENTITY_SDK: DEBUG
      #LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY: DEBUG
      #LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB: DEBUG
      HOST: ${HOST}
      SERVER_FORWARD_HEADERS_STRATEGY: framework
      IDENTITY_URL: http://identity.eng.ncgr.gov.sa
      CAMUNDA_IDENTITY_BASE_URL: http://identity.eng.ncgr.gov.sa
      SERVER_PORT: 8084
      IDENTITY_INITIAL_CLAIM_NAME: preferred_username
      IDENTITY_INITIAL_CLAIM_VALUE: my-admin-user
      IDENTITY_DATABASE_HOST: postgres
      IDENTITY_DATABASE_PORT: 5432
      IDENTITY_DATABASE_NAME: ${POSTGRES_DB}
      IDENTITY_DATABASE_USERNAME: ${POSTGRES_USER}
      IDENTITY_DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
      management.endpoints.web.exposure.include: health,configprops
      management.endpoint.health.probes.enabled: true
      MANAGEMENT_ENDPOINT_CONFIGPROPS_SHOW_VALUES: ALWAYS
      SPRING_PROFILES_ACTIVE: oidc
      CAMUNDA_IDENTITY_TYPE: GENERIC
      CAMUNDA_IDENTITY_ISSUER: https://my-idp-server
      CAMUNDA_IDENTITY_ISSUER_BACKEND_URL: https://my-idp-server
      CAMUNDA_IDENTITY_CLIENT_ID: management-identity-client
      CAMUNDA_IDENTITY_CLIENT_SECRET: management-identity-client-secret
      CAMUNDA_IDENTITY_AUDIENCE: camunda-api-audience
      CAMUNDA_IDENTITY_AUTH_SCOPES: openid profile offline_access camunda-api-scope      
      JAVA_TOOL_OPTIONS: "-Djavax.net.ssl.trustStore=/opt/certs/customTrustStore.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStoreType=JKS"
    healthcheck:
      test:
        [
          "CMD",
          "wget",
          "-q",
          "--tries=1",
          "--spider",
          "http://localhost:8082/actuator/health",
        ]
      interval: 15s
      timeout: 60s
      retries: 30
      start_period: 60s
    restart: unless-stopped
    volumes:
      - "/app/camunda/customTrustStore.jks:/opt/certs/customTrustStore.jks:ro"
    networks:
      - camunda-platform
      - identity-network
    extra_hosts:
      - "host.docker.internal:host-gateway"

  postgres:
    container_name: postgres
    image: postgres:${POSTGRES_VERSION}
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      interval: 10s
      timeout: 60s
      retries: 5
      start_period: 10s
    volumes:
      - postgres:/var/lib/postgresql/data
    networks:
      - identity-network
    extra_hosts:
      - "host.docker.internal:host-gateway"

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_VERSION}
    container_name: elasticsearch
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
      - bootstrap.memory_lock=true
      - discovery.type=single-node
      - xpack.security.enabled=false
      - cluster.routing.allocation.disk.threshold_enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    restart: unless-stopped
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s http://localhost:9200/_cluster/health | grep -E '\"status\":\"(yellow|green)\"' || exit 1",
        ]
      interval: 30s
      timeout: 60s
      retries: 5
      start_period: 60s
    volumes:
      - elastic:/usr/share/elasticsearch/data
    networks:
      - camunda-platform
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  orchestration:
  elastic:
  postgres:
  postgres-web:

networks:
  camunda-platform:
  identity-network:
  web-modeler:


my components url are:

operate:

http://workflow.mycompany.com/operate

tasklist:

http://workflow.mycompany.com/tasklist

embedded identity:

http://workflow.mycompany.com/identity

management identity:

http://identity.workflow.mycompany.com/

optimize:

http://workflow.mycompany.com/optimize

Does optimize need to be under a different dns name like management identity ?
and it can’t be served under same context path like operate and tasklist ?

Scenario:
1- http://workflow.mycompany.com/optimize
2- redirected to idp server login page: https://my-idp-server:8055/Account/Login

3- https://my-idp-server:8055/connect/authorize/callback?client_id=optimize-client-id&redirect_uri=http%3A%2F%2Fworkflow.mycompany.com%2Foptimize%2Fapi%2Fauthentication%2Fcallback&response_type=code&scope=openid%20profile%20offline_access%20camunda-api-scope&audience=optimize-api

4- http://workflow.mycompany.com/optimize/api/authentication/callback?code=E0741BA2BFCD6AE87BE24E034C032AF9472ABDA11D2D497D3591E40153D8E94B-1&scope=openid%20profile%20offline_access%20camunda-api-scope&session_state=0hQGj9371mK-IR1fTaIJuWWc4Zekv3-b7MAdav5iRGc.ECA90398893BD80C83ECA64D29551248&iss=https%3A%2F%2Fmy-idp-server%3A8055

5- Optimize logs shows 403 FORBIDDEN

Found out the issue, I had to log in to management identity > Mappings > Add mapping > Roles >

Mapping name: Optimize

Roles > Optimize

Claim name > sub

operator > EQUALS

value > my admin sub

And it worked fine.

Question, my identity provider doesn’t have a username claim but instead have a preferred_username claim, so if i want to make mapping rule to a custom claim like preferred_username how to accomplish that ?

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