Encryption Keys¶
Floh uses AES-256-GCM encryption for several categories of sensitive data. This document covers every key the application expects, how to generate them, and the procedures for rotating or migrating keys.
Key overview¶
| Environment variable | Purpose | Required in production? |
|---|---|---|
CONNECTOR_ENCRYPTION_KEY |
Encrypts connector secret fields at rest | Yes |
CONNECTOR_ENCRYPTION_KEY_PREVIOUS |
Allows decryption during key rotation | No (rotation only) |
SESSION_ENCRYPTION_KEY |
Encrypts OIDC access/refresh tokens in Redis | Yes |
Generating a key¶
All keys are 64-character hex strings (256 bits):
CONNECTOR_ENCRYPTION_KEY¶
Used to encrypt secret fields in connector_definition.connector_config
(fields marked secret: true in the connector's configSchema).
Development mode (NODE_ENV=development or test): if the variable
is unset or invalid the application falls back to an insecure all-zeros
key and logs a warning. This lets docker compose up work without any
configuration.
Production (NODE_ENV=production): the application will not start
if this key is missing or is not a valid 64-character hex string.
Key rotation¶
- Generate a new key:
openssl rand -hex 32 - Set the old key as
CONNECTOR_ENCRYPTION_KEY_PREVIOUS. - Set the new key as
CONNECTOR_ENCRYPTION_KEY. - Restart the server. Reads will transparently fall back to the previous key if decryption with the new key fails.
- Call the admin endpoint to re-encrypt all connectors:
curl -X POST https://your-server/api/connectors/rotate-keys \
-H "Authorization: Bearer <admin-token>"
The response includes a summary:
- Once all connectors are re-encrypted, remove
CONNECTOR_ENCRYPTION_KEY_PREVIOUSand restart.
SESSION_ENCRYPTION_KEY¶
Used to encrypt session data (OIDC access and refresh tokens) before
writing to Redis under floh:session:* keys.
Development mode: if unset, session data is stored as plaintext JSON in Redis.
Production: the application will not start without a valid key.
Rotation is not currently supported for session keys — sessions are short-lived (24h TTL) and will naturally expire under the old key. To rotate: set the new key and restart; all active sessions will be invalidated (users must re-authenticate).
Workflow & schedule variable encryption¶
Workflow variable definitions can include a secret: true flag. When
set, the corresponding variable values are encrypted at rest in
workflow_run.variables and scheduled_trigger.variables using the
CONNECTOR_ENCRYPTION_KEY.
In API responses, secret variable values are replaced with ********.
During workflow execution, secret values are decrypted for step
evaluation and re-encrypted before persisting.
Adding a secret variable¶
In the workflow definition's variables array, set secret: true:
Invitation token hashing¶
Invitation tokens (invitation_token.token) are stored as SHA-256 hashes
rather than plaintext. No encryption key is needed — the tokens have
sufficient entropy (32 random bytes) that a deterministic hash without
salt is secure.
When an invitation link is opened, the raw token from the URL is hashed before looking it up in the database. A database compromise therefore does not directly expose valid invitation tokens.
Migration 030_hash_invitation_tokens converts existing plaintext tokens
to hashes in place. This migration is irreversible.