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.shscript generates the key withopenssl rand -hex 32and stores it in.envasJWT_SIGNING_KEY. - The
orchestratorservice receives it through theBEEFLOW_SECRET_JWT_SYMMETRIC_KEYenvironment variable set indocker-compose.yml. - TheHive must be configured with the same value: through the
TH_ORCHESTRATOR_KEYenvironment variable, or throughorchestrator.jwt_signing_keyin the mountedapplication.confwhen 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.