Authentication and authorisation
Two separate questions, answered separately: who is calling, and are they allowed to do this.
Authentication
Present an API key:
Authorization: ApiKey did_test.a1b2c3.d4e5f6...
A key is three parts — a prefix, a client identifier and a secret. The prefix says which environment it belongs to; the client identifier says which key it is; the secret is compared in constant time against a stored hash.
Keys are stored hashed. DiligenceID cannot show you a key after it is issued, and support cannot recover one. Provision a new key instead.
Never put a key in a query string. Query strings are logged by proxies, load balancers and browsers.
Failure is 401 with no detail about whether the key ever existed, is revoked, or is expired. Distinguishing
those would let someone probe for valid identifiers.
What a key establishes
A key resolves three things, and none of them is taken from the request body:
| From | Why | |
|---|---|---|
| Tenant | The key | A caller must not be able to name someone else's tenant |
| Environment | The key prefix | A Sandbox key must not be able to ask for Production |
| Scopes | The key | Authorisation is granted, not requested |
A request that cannot resolve a tenant fails. There is no default.
Authorisation
Each operation declares the scope it needs. The reference page for every operation states it, and the machine-
readable form is in the specification as x-diligenceid-scope.
| Scope | Reaches |
|---|---|
organisations.read / .manage |
Organisations |
issuers.read / .manage |
Issuers, including configure and activate |
credential-configurations.read / .manage |
Credential types |
verification-policies.read / .manage |
Verification policies |
credentials.read |
Issuance transactions, credential status |
credentials.issue |
Issuing, and cancelling an issuance |
credentials.revoke |
Revocation |
verification.read |
Verification results |
verification.execute |
Running and cancelling verifications |
Read and manage are separate so a reporting integration can be given *.read and nothing else.
Missing scope is 403 — authenticated, not permitted. Distinct from 401, because the fixes are different:
401 means fix your key, 403 means fix your key's scopes.
Least privilege in practice
Give each integration its own key with only the scopes it uses. A revocation service does not need
credentials.issue; a dashboard does not need anything but read.
That costs nothing at setup and limits the blast radius of a leaked key to what that key could do.
What is not supported
OAuth client credentials — planned, not implemented. There is no token endpoint.
Browser-side keys — not supported and not safe. Anything shipped to a browser is readable by whoever is using it. Call DiligenceID from your server.
Per-user credentials — a key identifies an application, not a person. Your application knows which of its users triggered a request; DiligenceID does not.