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

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, use form, basic, oauth2 or keycloak — on Tomcat and WildFly with a protected Engine REST WAR, basic or oauth2.

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 has to enforce its own authentication, so disable-rest-security: true is the correct setting there (WebAdmin must not try to secure endpoints it doesn’t contain). But the Tomcat and WildFly distributions ship that WAR with its authentication filter commented out: turn it on as described in Production hardening. See also 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:

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:
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:

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:

Production hardening checklist

  • aseeflow.webadmin.authentication is never none (and no development Spring profile is active).
  • Spring Boot deployment: disable-rest-security is false.
  • Tomcat / WildFly: the Engine REST WAR’s authentication is on, and WebAdmin runs in basic or oauth2 through its proxy — see Production hardening.
  • 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:
Valid credentials succeed, wrong credentials fail (basic mode shown):
For OIDC modes, fetch a token and call REST with it:
Check that identities resolve — an authenticated user should see their groups: