Skip to main content
This page covers what you must configure to run ASEE Flow WebAdmin and its engine REST API safely in production. It builds on the Authentication and Deployment pages.
The demo ships deliberately permissive defaults for local development — a public client secret, open CORS (*), no audience validation, and (optionally) the no-auth none mode. Every one of these must be overridden before production. The checklist at the end of this page lists them.

Choose a production authentication mode

ModeProduction?Notes
basicHTTP Basic; credentials travel in every request, so require HTTPS. Good for headless/API clients.
formInternal onlySession-cookie login for the browser. External REST clients can’t authenticate (they get 401). Use when the only REST caller is the admin browser.
oauth2Standard OIDC (Okta, Entra ID, custom). Supports Bearer tokens for external clients when the resource server is configured (below).
keycloakOIDC plus live Keycloak directory integration (users, groups, tenants). Best for multi-tenant setups.
none❌ neverNo authentication — installs a synthetic demo user and permits all requests. Development only.
none is for local development only. As a safeguard, the starter refuses to start in none mode unless a development Spring profile (dev, demo, test, or local) is active — so it cannot be silently left enabled in production. For any real deployment, set authentication to basic, oauth2, or keycloak.

Never leave the engine REST API unprotected

aseeflow.webadmin.disable-rest-security removes /engine-rest/** from WebAdmin’s security chain. Its safety depends on the deployment:
  • Spring Boot (in-process engine) — there is no other security layer. Setting disable-rest-security: true leaves /engine-rest/** fully open: every request returns 200, even with wrong credentials. Keep it false.
  • WAR — the separate engine REST WAR enforces its own authentication, so disable-rest-security: true is the correct default there (WebAdmin must not try to secure endpoints it doesn’t contain). See Deployment.
If you ever disable REST security in a Spring Boot deployment, you must protect /engine-rest with a separate layer (reverse-proxy auth, mTLS, or network policy). Also enable the engine’s authorization framework in production so the engine enforces per-user permissions:
camunda.bpm:
  authorization:
    enabled: true

Secure the engine REST API (OIDC modes)

For oauth2 and keycloak, Bearer-token acceptance on /engine-rest is off by default and activates only when you set an issuer:
spring.security.oauth2.resourceserver.jwt:
  issuer-uri: ${keycloak.url.auth}/realms/aseeflow
  audiences:
    - account
Set audiences in production. With an empty audience list, only the issuer is validated — in a multi-tenant Keycloak realm, any token the realm signs is accepted, which is a privilege-escalation hole. List the audience your tokens actually carry.
Keycloak access tokens carry aud: "account" by default, not your client ID. To validate against the client ID instead, add an Audience mapper on the client in Keycloak (Clients → client → Client scopes → dedicated → Add mapper → Audience), then list that client ID in audiences. The REST chain always accepts the SSO session cookie; configuring the resource server makes it accept both a session and a Bearer token. There is no token-only/session-free REST surface.

Map identities correctly

Each login bridges the authenticated principal into the engine as a user ID plus resolved groups and tenants. Two misconfigurations cause silent lockouts:
  • User ID mismatch. The user-name-attribute claim (e.g. preferred_username, sub, email) becomes the engine user ID. If authorizations were assigned to a username but the token maps a UUID, the user logs in but resolves to zero groups and zero tenants — every query comes back empty. Make sure the claim matches the IDs the engine knows.
  • Missing group claim. In oauth2 mode the engine reads groups from a token claim (camunda.bpm.oauth2.identity-provider.group-name-attribute, default groups). If your provider doesn’t emit that claim, add a groups mapper on the provider. In keycloak mode the identity provider plugin queries Keycloak directly, so token group claims aren’t used.

Manage secrets

  • Never hard-code the OIDC client secret. Inject it via an environment variable (KEYCLOAK_CLIENT_SECRET) and keep the YAML referencing ${KEYCLOAK_CLIENT_SECRET:...}.
  • The demo’s fallback client secret and the demo / demo user are public and demo-only. Rotate the secret in your identity provider and create real users before production.
  • Never commit secrets, database passwords, or TLS keys. If one leaks into git history, rotate it immediately.

Transport security

  • Serve WebAdmin over HTTPS. Basic and form modes send credentials or session cookies that must not travel in clear text.
  • disableSSLCertificateValidation is development-only. The demo sets it true for a local self-signed Keycloak; in production remove it (or set false) and use a CA-trusted certificate on your issuer.
  • Behind a reverse proxy / load balancer: terminate HTTPS at the proxy and forward auth headers transparently. Register Keycloak redirect URIs against the external HTTPS URL (e.g. https://webadmin.example.com/webadmin/login/oauth2/code/keycloak), not the internal one, or OIDC login redirects break.
  • For session-based modes, set the session cookie to SameSite=Lax as a baseline CSRF defense:
    server.servlet.session.cookie.same-site: lax
    

Restrict CORS

CORS only matters when a cross-origin browser client (not the bundled UI) calls the REST API — relevant in oauth2 mode. The default is open (["*"]); restrict it to your real origins:
aseeflow:
  webadmin:
    cors:
      allowed-origins:
        - https://admin.example.com

Production hardening checklist

  • aseeflow.webadmin.authentication is basic, oauth2, or keycloak — never none or unset (and no development Spring profile is active).
  • Spring Boot deployment: disable-rest-security is false.
  • camunda.bpm.authorization.enabled: true.
  • OIDC with external clients: resourceserver.jwt.issuer-uri and audiences are set.
  • OIDC client secret supplied via environment variable; demo secret and demo user removed.
  • HTTPS everywhere; disableSSLCertificateValidation not true; issuer certificate trusted.
  • Keycloak redirect URIs point to the external HTTPS URL.
  • oauth2 mode: cors.allowed-origins restricted to real origins (not *).
  • Identity mapping tested — groups and tenants resolve (not empty).

Verify your configuration

Confirm endpoints are actually protected. Unauthenticated requests must be rejected:
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
  "http://localhost:8080/engine-rest/process-definition/count"
# Expected: 401 (or a 302 login redirect in form mode) — never 200
Valid credentials succeed, wrong credentials fail (basic mode shown):
curl -s -o /dev/null -w "%{http_code}\n" -u demo:demo    "http://localhost:8080/engine-rest/process-definition/count"   # 200
curl -s -o /dev/null -w "%{http_code}\n" -u demo:wrong   "http://localhost:8080/engine-rest/process-definition/count"   # 401
For OIDC modes, fetch a token and call REST with it:
TOKEN=$(curl -s -X POST \
  "http://localhost:9000/auth/realms/aseeflow/protocol/openid-connect/token" \
  -d grant_type=password -d client_id=aseeflow-identity-service \
  -d "client_secret=$KEYCLOAK_CLIENT_SECRET" \
  -d username=demo -d password=demo | jq -r .access_token)

curl -s -o /dev/null -w "HTTP %{http_code}\n" \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/engine-rest/process-definition/count"   # 200
Check that identities resolve — an authenticated user should see their groups:
curl -s -u demo:demo "http://localhost:8080/engine-rest/group?maxResults=50"
# Empty result usually means an identity-mapping problem (see "Map identities correctly").