Skip to content

Authentication Between TheHive Flow Components#

6.0 One

Every channel between TheHive Flow, TheHive, and the services of the stack carries its own authentication mechanism.

Docker Compose deployment

This page describes the Docker Compose deployment of TheHive Flow. On a Kubernetes deployment, see Configuration and operations on Kubernetes.

Authentication matrix#

Channel Mechanism Direction Where configured
TheHive → TheHive Flow JWT HS256, symmetric TheHive signs, TheHive Flow validates JWT_SIGNING_KEY in .env on TheHive Flow side, and TH_ORCHESTRATOR_KEY or orchestrator.jwt_signing_key on TheHive side
External system → Webhook trigger Per-webhook method: Basic Auth, header key, or JWT The caller authenticates each request The authentication section of the Webhook trigger
TheHive Flow → TheHive API key, bearer token TheHive Flow signs each request orchestrator/secret/thehive-api-key
TheHive Flow → PostgreSQL Username and password Connects as the orchestrator role Connection string in orchestrator/orchestrator.yml
Temporal → PostgreSQL Username and password Connects as the temporal role Connection string in temporal/.resolved.yaml
TheHive Flow → Temporal None Trust via network isolation The orchestrator-net Docker bridge
Nginx → TheHive Flow None Trust via network isolation The orchestrator-net Docker bridge

JWT between TheHive and TheHive Flow#

Both services use the same algorithm: HS256, an HMAC-SHA256 signature with a symmetric key.

  • The init.sh script generates the key with openssl rand -hex 32 and stores it in .env as JWT_SIGNING_KEY.
  • The orchestrator service receives it through the BEEFLOW_SECRET_JWT_SYMMETRIC_KEY environment variable set in docker-compose.yml.
  • TheHive must be configured with the same value: through the TH_ORCHESTRATOR_KEY environment variable, or through orchestrator.jwt_signing_key in the mounted application.conf when TheHive runs with --no-config.

There's no automated key exchange or rotation protocol. The key is set once at install time and rotated manually.

Tokens expire 1 minute after signing, with a 30-second validation leeway on TheHive Flow side. Keep the clocks of both hosts synchronized with NTP: a larger clock skew makes TheHive Flow reject every token as expired.

Common pitfall: Docker Compose environment variable syntax

With the list syntax, quotes become part of the value and cause a token signature is invalid error:

environment:
  - TH_ORCHESTRATOR_KEY="<jwt_signing_key>"

Use the mapping syntax instead, where YAML strips the quotes:

environment:
  TH_ORCHESTRATOR_KEY: "<jwt_signing_key>"

The list syntax also works without quotes:

environment:
  - TH_ORCHESTRATOR_KEY=<jwt_signing_key>

Direct API calls#

The REST API isn't a supported integration surface. To start workflows from your own systems, use Webhook triggers instead: they enter through nginx on port 443 and carry their own authentication method, independent of the JWT.

TheHive API key#

TheHive Flow uses a bearer token to authenticate outbound requests to TheHive. The token is read from the thehive-api-key file inside the configured secret_path: /secret in the container, mapped from ./orchestrator/secret/ on the host.

The file contains the raw token:

printf '%s' '<thehive_api_key>' > ./orchestrator/secret/thehive-api-key
chmod 644 ./orchestrator/secret/thehive-api-key

Mode 644 is required for the container user to read the file: see the secrets inventory.

Whitespace is trimmed from every secret

The loader trims leading and trailing whitespace and newlines from all secrets it resolves, whether from a file or a BEEFLOW_SECRET_* environment variable. This includes the JWT signing key, TheHive API key, and any Docker registry credentials such as passwords and identity or registry tokens. A trailing newline in a secret file is therefore harmless, and a secret value that must contain leading or trailing whitespace isn't supported.

PostgreSQL authentication#

The postgres/init-multi-db.sh script creates each database user at first container start, with passwords sourced from environment variables set in .env. Passwords are stored only in .env and in temporal/.resolved.yaml, both covered by .gitignore. They're never embedded in tracked configuration files.

Key rotation#

See Rotate secrets for the procedure of each key.

Next steps