Secrets managers and developer secret sync
LumoAuth can read from the secrets manager your team already runs, and write
freshly generated client credentials straight into your deploy platform.
Configure both under Organization portal → Integrations → Secrets & developer sync,
or at /orgs/{org}/portal/integrations/secrets. The page has two lists, Secrets managers and Deploy targets; pick a provider in the selector next to Add manager or Add target to open its form.

A connected secrets manager does three things:
- Resolves
secret://references in other integrations' configuration, so a credential lives in one place instead of being copied into LumoAuth. - Provides the token-vault KEK (key-encryption key) for bring-your-own-key envelope encryption of stored third-party OAuth tokens.
- Doppler only — doubles as a deploy target for client-credential sync.
Supported managers
| Manager | Authentication | Reference syntax |
|---|---|---|
| 1Password Connect | Connect server URL + Connect API token | op://<vault>/<item>/<field> — vault and item by name or 26-character id, field by label or id |
| Doppler | Service or personal token + project + config | The secret name, UPPER_SNAKE_CASE |
| Infisical | Universal Auth machine identity (client id + secret), project, environment, optional secret path | The secret name |
| AWS Secrets Manager | SigV4 (region, access key id, secret access key, optional session token / endpoint) | <name-or-arn>, or <name-or-arn>#<json-key> to pull one member out of a JSON secret |
| CyberArk Conjur | Appliance URL, account, login (e.g. host/lumoauth), API key | The variable id, e.g. prod/lumoauth/datadog-api-key |
| HashiCorp Vault / OpenBao KV v2 | Address + token, or AppRole role id + secret id; optional namespace and mount | <path>#<key> (key defaults to value) |
Every manager gets a Name, a Slug (its handle in secret:// references), an
Enabled switch, a Resolve secret:// references switch and an optional Hold the token-vault key switch (the Purposes section of the form). Credentials are encrypted at rest, all endpoints
must be public HTTPS hosts, requests pin the resolved IP, follow no redirects and
time out after 10 s. The Test connection action on a saved manager runs a live read and shows the
provider's own message.

The Purposes section of the form holds the Resolve secret:// references switch and the Hold the token-vault key (BYOK envelope encryption) switch.

Resolving secret:// references
Any integration credential can be a reference instead of a literal:
secret://<manager-slug>/<provider-specific-ref>
Examples:
secret://onepassword/op://Production/LumoAuth Datadog/api key
secret://doppler/DATADOG_API_KEY
secret://infisical/DATADOG_API_KEY
secret://aws/prod/lumoauth#datadog_api_key
secret://conjur/prod/lumoauth/datadog-api-key
secret://vault/lumoauth/prod#datadog_api_key
Rules:
- The slug must belong to an enabled manager with resolve references on; otherwise the reference is refused rather than silently ignored.
- Anything that is not a
secret://reference is returned unchanged, so a credential field accepts a literal or a reference interchangeably. - Resolved values are cached in memory for the request only — the secret is never written to the LumoAuth database.
- Failures are logged with the slug and a reason, never the value.
- Slugs are normalised (lower-cased, non-alphanumerics folded to
-), sosecret://My Vault/NAMEresolves against the manager with slugmy-vault.
Rotating a secret at the manager therefore takes effect on the next request with no change in LumoAuth.
References are resolved at the moment the credential is used, and the stored
configuration keeps the reference. This includes outbound SCIM (bearer token, Basic
password, OAuth 2.0 client secret), SMS providers, the organization's own e-mail
provider, developer secret sync targets, agent registries, AI gateways and device
posture integrations. Resolution fails closed: when a reference cannot be
resolved (manager disabled, resolve references off, secret missing, manager
unreachable) the call that needed it fails; the literal secret://… string is never
sent to the provider.
Token-vault BYOK (bring your own key)
The token vault stores the third-party OAuth tokens your agents use. By default those rows are sealed with the platform encryption key. Flag one secrets manager as the vault KEK and give it a reference, and LumoAuth fetches that secret, derives a 32-byte key from it with HKDF-SHA256, and seals rows under your key instead.
- The KEK must be at least 16 bytes (32+ recommended) and is cached for five minutes.
- Existing rows keep working. Turning BYOK on never breaks tokens that were already stored; they are re-encrypted under your key afterwards, and back under the platform key when you clear the flag.
- Revoking LumoAuth's access to the KEK makes every row sealed under it undecryptable — that is the point. Agents lose their linked connections until access is restored.
- Rotating the KEK at the manager invalidates rows sealed under the old one, so coordinate a rotation with LumoAuth before changing the value.
Developer secret sync
When you create an OAuth client or rotate its secret, LumoAuth shows the credentials exactly once. From that same screen, Sync credentials… (in the Sync credentials to a deploy target card) pushes them into a configured deploy target so nobody has to copy and paste them.
| Target | What is written | Configuration |
|---|---|---|
| Vercel | Project environment variables, upserted (POST /v10/projects/{id}/env?upsert=true) | Token, project id, optional team id, optional targets (production, preview, development) |
| Netlify | Account (optionally site-scoped) environment variables | Personal access token, account slug, optional site id |
| GitHub Actions | Repository or environment secrets | Fine-grained PAT with Secrets: write, owner, repo, optional environment |
| Doppler | Secrets in one project/config | Service token, project, config |
Variable names are LUMO_CLIENT_ID and LUMO_CLIENT_SECRET and must be
UPPER_SNAKE_CASE; anything else is rejected before a request is made. Names
ending in _SECRET are marked sensitive where the platform supports it
(Vercel sensitive, Netlify is_secret).
GitHub Actions never receives a plaintext secret: LumoAuth fetches the
repository (or environment) public key and seals each value with libsodium
crypto_box_seal before the PUT, exactly as GitHub requires. The public key is
fetched once per push.
Target credentials are encrypted at rest like every other integration, and each target has a Test connection action that verifies the token and scope without writing anything.

Troubleshooting
| Symptom | Cause |
|---|---|
| No enabled secrets manager with slug "x" | The slug in the reference does not match an enabled manager for this organization |
| Secrets manager "x" is not allowed to resolve references | The manager exists but resolve references is off |
| Blocked … URL (must be a public HTTPS address) | The endpoint is http://, a private address or otherwise fails the SSRF guard |
| Token vault row is BYOK-encrypted (v2) but the organization has no vault KEK configured | The vault KEK flag was cleared while v2 rows still exist — re-enable it |
| Token vault v2 decryption failed (wrong or rotated KEK) | The KEK changed at the manager after rows were sealed; restore the previous value or re-link the affected connections |