API key security
A DiligenceID API key is a long-lived bearer credential. Whoever holds it can do everything its scopes allow, as your tenant, in its environment.
The rules
Never in source control. Including in history, and including a private repository. A key pushed to a repository should be treated as compromised immediately — rewriting history does not un-disclose it.
Never in a browser. Anything shipped to a browser is readable by whoever is using it. Call DiligenceID from your server and have the browser call your own backend.
Never in a query string. Query strings are logged by proxies, load balancers, CDNs and browsers. Use the
Authorization header.
Never in a log. Both SDKs make this hard: their credential types reveal nothing when interpolated or serialised. If you handle the key directly, do the same.
Never in a screenshot, a support ticket or a chat message. If a key has been shared to diagnose something, rotate it afterwards.
Storage
Read the key at startup from a secret store — Key Vault, a secrets manager, or your platform's equivalent. Not from a checked-in configuration file, and not baked into a container image.
DiligenceID stores keys hashed. It cannot show you a key after issuing it, and support cannot recover one. That is deliberate: a system that can show you your key is a system that can be made to show it to someone else.
Least privilege
Give each integration its own key with only the scopes it uses.
| Integration | Scopes |
|---|---|
| Issuance service | credentials.issue, credentials.read |
| Revocation service | credentials.revoke, credentials.read |
| Verifier | verification.execute, verification.read |
| Setup pipeline | The *.manage scopes it configures |
| Reporting | *.read only |
This costs nothing at setup and limits a leaked key to what that key could do. A leaked reporting key that cannot issue is a very different incident from one that can.
Environment separation
did_test. reaches Sandbox, did_live. reaches Production, and neither reaches the other.
Assert on the prefix at startup. A test suite that silently pointed at Production would issue real credentials to real people, and the first sign would be a support call.
if (!credential.IsSandbox) throw new InvalidOperationException("Refusing to run tests against production.");
Rotation
Rotate on a schedule, when someone with access leaves, and immediately on any suspicion of exposure. Provision the new key, deploy alongside, confirm traffic moved, then revoke the old one — never revoke first.
If a key is exposed
- Revoke it. Do this before investigating.
- Establish what it could reach: environment and scopes.
- Review what was done with it.
- Provision a replacement and deploy.
- Fix how it escaped.