WebModeler API REST Authentication

I started a Docker Compose cluster with a multitenant configuration of Camunda 8.8.1.
I followed this guide: https://docs.camunda.io/docs/apis-tools/web-modeler-api/authentication/
to create an application that can search all projects in Web Modeler.


I’m able to obtain the JWT token with the following call:

curl --location --request POST ‘http://localhost:18080/auth/realms/camunda-platform/protocol/openid-connect/token’ 
–header ‘Content-Type: application/x-www-form-urlencoded’ 
–data-urlencode “client_id=${CLIENT_ID}” 
–data-urlencode “client_secret=${CLIENT_SECRET}” 
–data-urlencode ‘grant_type=client_credentials’

My decoded JWT looks like this:

{
  "exp": 1762180456,
  "iat": 1762180156,
  "jti": "trrtcc:bad662ac-f005-38cd-6d31-b3e012f41566",
  "iss": "http://localhost:18080/auth/realms/camunda-platform",
  "aud": [
    "webmodelerconfigurator",
    "web-modeler-api",
    "camunda-identity-resource-server",
    "account"
  ],
  "sub": "519465b1-f09f-4dab-a52c-e8140cf467b0",
  "typ": "Bearer",
  "azp": "webmodelerconfigurator",
  "acr": "1",
  "allowed-origins": [],
  "realm_access": {
    "roles": [
      "Default user role"
    ]
  },
  "resource_access": {
    "web-modeler-api": {
      "roles": [
        "write:*",
        "admin:*"
      ]
    },
    "camunda-identity-resource-server": {
      "roles": [
        "read:users",
        "read",
        "write"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "profile email",
  "clientHost": "172.19.0.1",
  "email_verified": false,
  "permissions": {
    "web-modeler-api": [
      "write:*",
      "admin:*"
    ],
    "camunda-identity-resource-server": [
      "read:users",
      "read",
      "write"
    ],
    "account": [
      "manage-account",
      "manage-account-links",
      "view-profile"
    ]
  },
  "preferred_username": "service-account-webmodelerconfigurator",
  "clientAddress": "172.19.0.1",
  "client_id": "webmodelerconfigurator"
}

But when I use it in my Swagger (at http://localhost:8070/swagger-ui/index.html#/Projects/searchProjects), I get an UNAUTHORIZED error.
The web-modeler-restapi cotainer say:

2025-11-03 14:31:32.710  WARN 1 --- [  XNIO-1 task-2] [311d2908-4e96-4c4b-a925-8e363f0cb8fe] s.a.j.SelfManagedPublicApiTokenConverter : Failed to verify audience claim for token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkOGFfZUp3QVFOd1l2LWNYVVY4RVBUczZ3STdHLXhaS1BGQXFsNnZrZWhNIn0.eyJleHAiOjE3NjIxODA1NDIsImlhdCI6MTc2MjE4MDI0MiwianRpIjoidHJydGNjOjlmNmJjYTZjLTFiYmUtNGYyZC1jYTliLTlkYzJlZGU5NTEyNyIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MTgwODAvYXV0aC9yZWFsbXMvY2FtdW5kYS1wbGF0Zm9ybSIsImF1ZCI6WyJ3ZWJtb2RlbGVyY29uZmlndXJhdG9yIiwid2ViLW1vZGVsZXItYXBpIiwiY2FtdW5kYS1pZGVudGl0eS1yZXNvdXJjZS1zZXJ2ZXIiLCJhY2NvdW50Il0sInN1YiI6IjUxOTQ2NWIxLWYwOWYtNGRhYi1hNTJjLWU4MTQwY2Y0NjdiMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndlYm1vZGVsZXJjb25maWd1cmF0b3IiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIkRlZmF1bHQgdXNlciByb2xlIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsid2ViLW1vZGVsZXItYXBpIjp7InJvbGVzIjpbIndyaXRlOioiLCJhZG1pbjoqIl19LCJjYW11bmRhLWlkZW50aXR5LXJlc291cmNlLXNlcnZlciI6eyJyb2xlcyI6WyJyZWFkOnVzZXJzIiwicmVhZCIsIndyaXRlIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJjbGllbnRIb3N0IjoiMTcyLjE5LjAuMSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGVybWlzc2lvbnMiOnsid2ViLW1vZGVsZXItYXBpIjpbIndyaXRlOioiLCJhZG1pbjoqIl0sImNhbXVuZGEtaWRlbnRpdHktcmVzb3VyY2Utc2VydmVyIjpbInJlYWQ6dXNlcnMiLCJyZWFkIiwid3JpdGUiXSwiYWNjb3VudCI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19LCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQtd2VibW9kZWxlcmNvbmZpZ3VyYXRvciIsImNsaWVudEFkZHJlc3MiOiIxNzIuMTkuMC4xIiwiY2xpZW50X2lkIjoid2VibW9kZWxlcmNvbmZpZ3VyYXRvciJ9.MMu7qXqKr4hftQsdSOUJNN_NAsuaAjOe0KXUzqb4BOyfWpjbMzrUV6NP4tsNLU8yaga-yVuZuriFUy_RCgK6cXCdEC0fZ3NBuc-hvdtDrc06ALgtPP5GpLwXQJfVkZxdG6rOR_yxZe9N1kIgLS2n2sdZZ7K4esBolZgjA6285H7nnGPYkAMzJvvmVNaYCFoOD6gxtwe79xNtzJsnrNQ9pEHFxST-O71-2jzO7hQZvkusclTfL2-4uh_Nv_-19x6VPLIwZNvih0oi3bb2rTVZopJ-FTM_bU1MkdH6vrUz-I4Ter1NEgvBD6kAYR9d4TxdFlk7C32zkP3HIMlcWHQecQ
2025-11-03 14:31:32.711  INFO 1 --- [  XNIO-1 task-2] [311d2908-4e96-4c4b-a925-8e363f0cb8fe] i.c.m.util.logging.RequestLoggingFilter  : "POST /api/v1/projects/search, headers=[sec-fetch-mode:"cors", referer:"http://localhost:8070/swagger-ui/index.html", content-length:"50", sec-fetch-site:"same-origin", accept-language:"en,it-IT;q=0.9,it;q=0.8,en-US;q=0.7", origin:"http://localhost:8070", Connection:"keep-alive", x-correlation-id:"311d2908-4e96-4c4b-a925-8e363f0cb8fe", Host:"web-modeler-restapi:8081", accept:"application/json", accept-charset:"utf-8", authorization:"masked", sec-ch-ua:""Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"", sec-ch-ua-mobile:"?0", sec-ch-ua-platform:""Windows"", accept-encoding:"gzip, deflate, br, zstd", user-agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36", sec-fetch-dest:"empty", Content-Type:"application/json;charset=UTF-8"]" - 401 UNAUTHORIZED

I get the same behavior with a cURL call like this:

curl --request POST \
  --url "http://localhost:8070/api/v1/projects/search" \
  --header 'accept: application/json' \
  --header "authorization: Bearer ${CAMUNDA_OAUTH_TOKEN}" \
  --header 'content-type: application/json' \
  --data "$PAYLOAD"

What is the problem?

Hi @Cristiano_Carretti,

The “Failed to verify audience claim for token” error you’re encountering is a common authentication issue in self-managed Web Modeler setups. This happens when there’s a mismatch between the aud (audience) claim in your JWT token and what the Web Modeler API expects.

Root Cause Analysis

Looking at your JWT token, I can see the audience claim contains:

"aud": [
  "webmodelerconfigurator",
  "web-modeler-api",
  "camunda-identity-resource-server",
  "account"
]

The issue is likely that your Web Modeler REST API is configured to expect a different audience value than what’s in your token.

Solution Steps

1. Check Your Web Modeler Configuration

First, verify the audience configuration in your Docker Compose setup. The Web Modeler REST API uses these environment variables:

  • CAMUNDA_MODELER_SECURITY_JWT_AUDIENCE_INTERNAL_API - for internal API calls
  • CAMUNDA_MODELER_SECURITY_JWT_AUDIENCE_PUBLIC_API - for public API calls

These should typically be set to web-modeler-api for the REST API.

2. Update Your Token Request

Try adding the audience parameter to your token request:

curl --location --request POST 'http://localhost:18080/auth/realms/camunda-platform/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'audience=web-modeler-api'

3. Verify Your Keycloak Client Configuration

In your Keycloak admin console, check that your webmodelerconfigurator client is properly configured with the correct audience mappers and that it matches your Web Modeler environment variables.

4. Debug Steps

To troubleshoot further:

  1. Inspect your Docker Compose file - Look for the Web Modeler REST API service and check the audience-related environment variables
  2. Check the JWT token - Use jwt.io to decode your token and verify the aud claim
  3. Compare configurations - Ensure the audience in your JWT matches what Web Modeler expects

Expected Configuration

For a typical setup, your Web Modeler REST API should have:

environment:
  CAMUNDA_MODELER_SECURITY_JWT_AUDIENCE_PUBLIC_API: "web-modeler-api"

And your token request should include audience=web-modeler-api.

Can you check your Docker Compose configuration for the Web Modeler services and share the relevant environment variables? This will help us identify the exact mismatch.

References:

Perfect! I created the create/update/delete/read permissions as mentioned here: Manage access and permissions | Camunda 8 Docs, and I assigned them to my clients — now everything works fine.

Just one question: is there a way to determine if a folder returned from the WebModeler API read operation is a Process Application rather than a simple folder?

Thank you
Cristiano

Great to hear that you got the authentication working by setting up the proper permissions! :tada:

Regarding your question about distinguishing Process Application folders from regular folders in the Web Modeler API response:

Unfortunately, the current Web Modeler API documentation doesn’t specify a direct property or field in the folder response that explicitly identifies whether a folder is a Process Application or a regular folder.

What We Know About Process Applications vs Regular Folders

Process Application folders have these characteristics:

  • Must have a main process BPMN diagram assigned
  • Support versioning and bulk deployment of all contained assets together
  • Cannot contain subfolders (unlike regular folders)
  • Support process application-specific operations like application-level versioning

Regular folders are more flexible:

  • Can contain any files and subfolders
  • Files can be versioned individually
  • Don’t have the deployment bundling capabilities

Potential Workarounds

Since there’s no explicit type field in the API response, you might need to use indirect methods to identify Process Applications:

  1. Check for subfolders: Process Applications cannot contain subfolders, so if a folder has no subfolders and contains BPMN files, it might be a Process Application

  2. Attempt Process Application-specific operations: Try using Process Application-specific API endpoints (like application-level versioning) - these will fail for regular folders

  3. Analyze folder structure: Process Applications typically have a specific structure with a main process and related assets

Recommendation

I’d suggest checking the actual API response structure when you call the projects/folders endpoints to see if there are any undocumented fields that might indicate the folder type. You could also consider reaching out to Camunda support or filing a feature request for this functionality if it’s important for your use case.

References:

Would you like me to help you explore any of these workaround approaches?

So when creating via API I have no way to create a Process Application equal to the one created via UI?

That’s a great question! The answer is a bit nuanced:

Current API Limitations

You’re correct that there’s no direct API endpoint to create a Process Application exactly as the UI does. The Web Modeler API currently only provides a generic project creation endpoint (POST /projects).

What You Can Do via API

Here’s what’s possible and what’s missing:

:white_check_mark: What Works:

  1. Create a project using POST /projects
  2. Add BPMN files to the project using file creation endpoints
  3. Add related files (DMN, forms, etc.) to the project
  4. Structure the project to follow Process Application conventions

:cross_mark: What’s Missing:

  1. No way to designate a “main process” via API
  2. No cluster assignment during creation via API
  3. No explicit Process Application type flag or property
  4. No Process Application-specific creation endpoint

The Gap

When you create a Process Application in the UI, it:

  • Prompts you to select a development cluster
  • Automatically creates and assigns a main process
  • Sets up the proper Process Application structure
  • Enables Process Application-specific features (like application-level versioning)

The API currently doesn’t provide these Process Application-specific setup steps.

Workaround Approach

You can create something functionally similar to a Process Application via API:

// 1. Create a project
const project = await createProject({ name: "My Process App" });

// 2. Create a main BPMN process
const mainProcess = await createFile({
  projectId: project.id,
  name: "main-process.bpmn",
  content: "<!-- BPMN content -->"
});

// 3. Add related files (DMN, forms, etc.)
// 4. Follow Process Application structure conventions

But this won’t have the same Process Application features as one created through the UI.

Recommendation

This seems like a legitimate feature gap. I’d suggest:

  1. Filing a feature request for Process Application creation via API
  2. Contacting Camunda support to confirm current limitations and roadmap

The API should ideally support the same functionality as the UI for creating Process Applications with proper main process assignment and cluster configuration.

References:

Would you like help filing a feature request for this functionality?