How to generate an access token for /v1 and /v2 APIs for operate, tasklist etc. when diretcly integrated with Entra ID

Hello,
We have a Camunda 8.6.7 integrated directly with Entra ID. There is no documentation how to generate an access token for /v1 Tasklist and operate APIs. This doc assumes keycloak is enabled, We don’t have keycloak and using cookies.txt does not seem right because Entra ID use login requires a MFA.

I tried using Operate and Tasklist’s client_id / secret for the registered apps in Entra ID. Using Entra ID’s https://login.microsoftonline.com/'${tenantId}'/oauth2/v2.0/token, we can generate a JWT token, however, this

curl --request POST ${baseUrl}/operate/v1/process-instances/search \
   --header "Authorization: Bearer ${accessToken}" \
   --header 'Content-Type: application/json' \
   --data-raw '{}'

fails with error:

{"message":"An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature"}

We have confirmed the generated JWT signature is verified and valid. That error message is incorrect. But the bigger problem is I cannot make any API calls.

Any insight into how to do this?

Regards,
Atul

Hi @atultewari - I understand you’re working with one of our sales engineers on a related issue with EntraID already. I strongly suspect that this issue, while different, is related. We’ve asked the engineering team to take a look and weigh in, but it might take a couple days as most of the engineering team is at an off-site team meetup this week. (I’ve set a reminder on my calendar to follow up when they are back.)

Thank you @nathan.loding Camunda sales engineers I’m working with are out this week and they had pulled in another engineer while they are away this week. I have not heard back. It would be awesome if you can follow up with them.

Regards,
Atul

Hi @atultewari - I chatted with one of our engineers, and he was able to use EntraID to access both v1 and v2 endpoints. Here’s a demonstration: https://www.youtube.com/watch?v=CFucxd5RCgA

Are you able to share your Identity and Operate configurations (with secrets redacted of course)?

Thank you @nathan.loding Would the engineer be able to share the converted “curl”. I did not have success with our Entra ID integration. BTW, is there a way to hide credentials within operate where variables are displayed as plaintext?

Identity

identity:
  url: "https://dev-camunda.abcdefg.dev/identity"
  flags:
    multi-tenancy: "false"
  client-id: ${CAMUNDA_IDENTITY_CLIENT_ID:}
  client-secret: ${CAMUNDA_IDENTITY_CLIENT_SECRET:}

  authProvider:
    type: "MICROSOFT"
    issuer-url: "https://login.microsoftonline.com/redacted-tenant-id/v2.0"
    backend-url: "https://login.microsoftonline.com/redacted-tenant-id/v2.0"

  component-presets:
    connectors:
      applications:
        - name: Connectors
          id: ${CAMUNDA_CONNECTORS_CLIENT_ID:${KEYCLOAK_INIT_CONNECTORS_CLIENT_ID:connectors}}
          type: m2m
          secret: ${CAMUNDA_CONNECTORS_SECRET:${KEYCLOAK_INIT_CONNECTORS_SECRET:}}
          permissions:
            - audience: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"
              definition: read:*
    console:
      applications:
        - name: "Console"
          id: ${CAMUNDA_CONSOLE_CLIENT_ID:${KEYCLOAK_INIT_CONSOLE_CLIENT_ID:console}}
          type: public
          root-url: "https://dev-camunda.abcdefg.dev/console"
          redirect-uris:
            - "/"
      apis:
        - name: Console API
          audience: "bd34c6e3-fb1f-4ff4-8af7-e3c2d9112ba3"
          permissions:
            - definition: write:*
              description: "Write permission"
      roles:
        - name: "Console"
          description: "Grants full access to Console"
          permissions:
            - audience: "bd34c6e3-fb1f-4ff4-8af7-e3c2d9112ba3"
              definition: write:*
    identity:
      apis:
        - name: "Camunda Identity Resource Server"
          audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
          permissions:
            - definition: read
              description: "Read permission"
            - definition: "read:users"
              description: "Read users permission"
            - definition: write
              description: "Write permission"
      roles:
        - name: "Identity"
          description: "Provides full access to Identity"
          permissions:
            - audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
              definition: read
            - audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
              definition: write
    operate:
      applications:
        - name: Operate
          id: ${CAMUNDA_OPERATE_CLIENT_ID:${KEYCLOAK_INIT_OPERATE_CLIENT_ID:operate}}
          type: confidential
          secret: ${CAMUNDA_OPERATE_SECRET:${KEYCLOAK_INIT_OPERATE_SECRET:}}
          root-url: "https://dev-camunda.abcdefg.dev/operate"
          redirect-uris:
            - "/identity-callback"
      apis:
        - name: Operate API
          audience: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"
          permissions:
            - definition: read:*
              description: "Read permission"
            - definition: write:*
              description: "Write permission"
      roles:
        - name: "Operate"
          description: "Grants full access to Operate"
          permissions:
            - audience: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"
              definition: read:*
            - audience: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"
              definition: write:*
    optimize:
      applications:
        - name: Optimize
          id: ${CAMUNDA_OPTIMIZE_CLIENT_ID:${KEYCLOAK_INIT_OPTIMIZE_CLIENT_ID:optimize}}
          type: confidential
          secret: ${CAMUNDA_OPTIMIZE_SECRET:${KEYCLOAK_INIT_OPTIMIZE_SECRET:}}
          root-url: "https://dev-camunda.abcdefg.dev/optimize"
          redirect-uris:
            - "/api/authentication/callback"
      apis:
        - name: Optimize API
          audience: "6532024f-0777-4550-93a3-7438834958ee"
          permissions:
            - definition: write:*
              description: "Write permission"
      roles:
        - name: "Optimize"
          description: "Grants full access to Optimize"
          permissions:
            - audience: "6532024f-0777-4550-93a3-7438834958ee"
              definition: write:*
            - audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
              definition: read:users
    tasklist:
      applications:
        - name: Tasklist
          id: ${CAMUNDA_TASKLIST_CLIENT_ID:${KEYCLOAK_INIT_TASKLIST_CLIENT_ID:tasklist}}
          type: confidential
          secret: ${CAMUNDA_TASKLIST_SECRET:${KEYCLOAK_INIT_TASKLIST_SECRET:}}
          root-url: "https://dev-camunda.abcdefg.dev/tasklist"
          redirect-uris:
            - "/identity-callback"
      apis:
        - name: Tasklist API
          audience: "a12693be-990e-4756-a504-9f7fdfa796fd"
          permissions:
            - definition: read:*
              description: "Read permission"
            - definition: write:*
              description: "Write permission"
      roles:
        - name: "Tasklist"
          description: "Grants full access to Tasklist"
          permissions:
            - audience: "a12693be-990e-4756-a504-9f7fdfa796fd"
              definition: read:*
            - audience: "a12693be-990e-4756-a504-9f7fdfa796fd"
              definition: write:*
    webmodeler:
      applications:
        - name: "Web Modeler"
          id: ${CAMUNDA_WEBMODELER_CLIENT_ID:${KEYCLOAK_INIT_WEBMODELER_CLIENT_ID:web-modeler}}
          type: public
          root-url: "https://dev-camunda.abcdefg.dev/modeler"
          redirect-uris:
            - "/login-callback"
      apis:
        - name: Web Modeler Internal API
          audience: "3dc81738-bb8a-4fa1-8bdd-3a85568d76db"
          permissions:
            - definition: write:*
              description: "Write permission"
            - definition: admin:*
              description: "Admin permission"
        - name: Web Modeler API
          audience: "3dc81738-bb8a-4fa1-8bdd-3a85568d76db"
          permissions:
            - definition: create:*
              description: "Allows create access for all resources"
            - definition: read:*
              description: "Allows read access to all resources"
            - definition: update:*
              description: "Allows update access to all resources"
            - definition: delete:*
              description: "Allows delete access for all resources"
      roles:
        - name: "Web Modeler"
          description: "Grants full access to Web Modeler"
          permissions:
            - audience: "3dc81738-bb8a-4fa1-8bdd-3a85568d76db"
              definition: write:*
            - audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
              definition: read:users
        - name: "Web Modeler Admin"
          description: "Grants elevated access to Web Modeler"
          permissions:
            - audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
              definition: read:users
            - audience: "3dc81738-bb8a-4fa1-8bdd-3a85568d76db"
              definition: write:*
            - audience: "3dc81738-bb8a-4fa1-8bdd-3a85568d76db"
              definition: admin:*
    zeebe:
      apis:
        - name: Zeebe API
          audience: "05a4e890-595f-494e-8d81-7371854625ca"
          permissions:
            - definition: write:*
              description: "Write permission"
      roles:
        - name: "Zeebe"
          description: "Grants full access to the Zeebe API"
          permissions:
            - audience: "05a4e890-595f-494e-8d81-7371854625ca"
              definition: write:*
server:
  port: 8080
  servlet:
    context-path: "/identity"

spring:
  profiles:
    active: oidc
  datasource:
    url: "jdbc:postgresql://camunda-identity-postgresql:5432/identity"
    username: "identity"

camunda:
  identity:
    audience: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
    client-id: "3691ccd7-8e49-4401-9fb3-c6f226353bc7"
    baseUrl: "http://camunda-identity:80/identity"
    issuer: "https://login.microsoftonline.com/redacted-tenant-id/v2.0"
    issuerBackendUrl: "https://login.microsoftonline.com/redacted-tenant-id/v2.0"

Operate

server:
  servlet:
    context-path: "/operate"
management:
  server:
    base-path: "/operate"
spring:
  profiles:
    active: "identity-auth"
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: "https://login.microsoftonline.com/redacted-tenant-id/v2.0"
          jwk-set-uri: "https://login.microsoftonline.com/redacted-tenant-id/discovery/v2.0/keys"

camunda:
  identity:
    clientId: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"
    audience: "33b6cfe5-f4e4-4e2a-9136-952c5016a7ac"

# Camunda Database configuration
camunda.database:
  type: elasticsearch
  # Cluster name
  clusterName: elasticsearch
  # Elasticsearch full url
  url: "http://camunda-elasticsearch:9200"

# Operate configuration file
camunda.operate:
  identity:
    redirectRootUrl: "https://dev-camunda.abcdefg.dev"

  # ELS instance to store Operate data
  elasticsearch:
    # Cluster name
    clusterName: elasticsearch
    # Host
    host: camunda-elasticsearch
    # Transport port
    port: 9200
    # Elasticsearch full url
    url: "http://camunda-elasticsearch:9200"
  # ELS instance to export Zeebe data to
  zeebeElasticsearch:
    # Cluster name
    clusterName: elasticsearch
    # Host
    host: camunda-elasticsearch
    # Transport port
    port: 9200
    # Index prefix, configured in Zeebe Elasticsearch exporter
    prefix: zeebe-record
    # Elasticsearch full url
    url: "http://camunda-elasticsearch:9200"
  # Zeebe instance
  zeebe:
    # Gateway address
    gatewayAddress: "camunda-zeebe-gateway:26500"
logging:
  level:
    ROOT: INFO
    io.camunda.operate: INFO
#Spring Boot Actuator endpoints to be exposed
management.endpoints.web.exposure.include: health,info,conditions,configprops,prometheus,loggers,usage-metrics,backups

@atultewari - what credentials are visible within Operate? Do you mean process variables or something else?

Looking at your configuration, I wonder if you need to explicitly set the JWKS URL. Have a look at the configuration options here (there are similar ones for Tasklist and Optimize also), specifically the spring.security.oauth2.resourceserver.jwt.issueruri setting:

Thanks @nathan.loding The link you sent was related to Camunda 8.3. I presume some of those still work within 8.6.

Also, when we integrate Camunda directly with Entra ID (without keycloak), the only 2 features available within Camunda Identity webapp are:

  • Roles
  • Mappings

There are no features / tabs related to API, Application, Groups, Users. Is that expected? Will future versions of Camunda Identity have other features enabled, or are we missing some configuration when we directly integrated with Entra ID?

Yes, I meant process variables. Operate should not display sensitive variable values, like passwords, secrets, etc. Anyway we can hide these process variables?

@atultewari - oops, I had the wrong version open, but you can toggle the version in the top left of the docs. Here’s the 8.6 link: Authentication and authorization | Camunda 8 Docs

As for API, applications, groups, etc. - that is all configured within EntraID, not Identity. Identity is simply the interface that allows all the components to authenticate and authorize against your OIDC server. For instance, if you look at the “Additional Considerations” in the documentation, you can create and use a M2M token (which is what “Applications” are within identity, machine-to-machine tokens), you use the client_credentials grant type; for a user-facing flow, you would want to use the authorization_code grant.

As for Operate, we strongly recommend you do not include sensitive data in your processes, and instead use a reference to that data that your application/job workers can understand. Or, in the case of passwords/keys/etc., we recommend you use Secrets. Operate has no concept of what data is sensitive or not.