Why this matters#
As soon as more than one system is involved in sending a message (a journey tool calling a messaging API, a support desk sending on behalf of a client, a partner integration acting for its customers), someone will eventually ask: who authorised this message, for whom, and was that permission still valid? If the only credential in the picture is a shared API key, nobody can answer. This piece explains the gap, why it appears, and the well-established patterns from the wider security world that close it. It is relevant to buyers as much as builders: how a provider handles this tells you a lot about how safely you can connect it to everything else.
Look at the credentials your messaging stack issues. There is probably an API key per account, and possibly scopes on it. That covers "this application may send".
It does not cover the question that actually arises in any integrated system: on whose behalf, and for how long?
Why the gap exists#
Because it did not matter when a platform was called by one backend belonging to one company. The key was the identity, and the answer to "on whose behalf" was "the account holder, obviously".
It stops being obvious the moment anything is layered. A journey engine calls a messaging API for one of its customers. An agent desk sends on behalf of the tenant whose queue it is serving. A partner integration acts for a client who can revoke that arrangement.
In each case the credential says who is calling. Nothing says who they are calling for.
User identity was solved first because the pressure was visible: there are many users, they leave, they get phished, and failures make headlines. That pressure produced OAuth, OpenID Connect and SAML. Service identity never had that pressure. Services are few and internal, and a shared secret works, until it is in eleven places, one of them a build pipeline nobody owns.
Who the call is for, as it travels
- 01End customer
Authorises a partner to act for them
Nothing in the credential records this
- 02Partner integration
Calls with a shared key
The key says who is calling
- 03Journey engine
Calls the messaging API for its customer
Still only who is calling
- 04Messaging API
Sees a valid key — and nothing about whom the message is for
What goes wrong without it#
Revocation is all-or-nothing. A partner's access is a shared key. Withdrawing one customer's authorisation means rotating a credential that everyone else is also using.
Audit answers the wrong question. Logs record which key sent a message. Reconstructing which end customer authorised it means joining application logs that may not have been retained.
The blast radius is the whole account. A leaked integration key can send as anybody the integration serves.
Consent enforcement lands in the wrong place. The system holding the consent ledger is often not the system holding the credential. Without a way to say "I am acting for this person", the check has to be trusted to the caller, which means it is not a check.
The absence of service identity does not announce itself. It shows up as a sequence of small compromises, each reasonable on its own.
How a shared secret becomes an incident
- 01One key, one integration
Perfectly fine. It is scoped by accident, because there is only one caller.
- 02A second caller borrows it
Nobody wants to run the provisioning process twice. The key is now shared.
- 03The key acquires scope
It needs to do more, so it is granted more. Nothing revokes the parts it stopped needing.
- 04Rotation becomes impossible
Rotating it means coordinating every holder, and nobody knows who holds it.
- 05A holder is compromised
Now everything the key can do is available, and you cannot tell which holder did what.
Four failures a shared key produces
- Revocation is all-or-nothing
Withdrawing one customer means rotating a key everyone else uses
- Audit answers the wrong question
It records which key, not which customer authorised the message
- The blast radius is the whole account
A leaked key sends as anybody the integration serves
- Consent enforcement lands in the wrong place
The check is trusted to the caller, so it is not a check
The shape of the answer#
The pattern is well established outside this category and less often applied inside it.
| Long-lived shared API key | Short-lived delegated token | |
|---|---|---|
| Lifetime | Months or years | Minutes or hours |
| Says who is calling | Usually | Yes |
| Says which customer it is for | No | Yes, as an explicit claim |
| Scope | Often "everything this account can do" | One capability, one audience, one channel |
| Revoking one customer | Rotate the key for everyone | Revoke that one grant |
| If leaked | Works until someone notices | Expires on its own |
| Audit trail | Which key sent it | Which grant, for whom, issued by whom |
In practice that means:
- A short-lived token, not a long-lived key. Minutes, obtained in exchange for a durable credential. A leaked token expires; a leaked key has to be discovered.
- An explicit subject claim. The token says which end customer this action is for. The receiving system enforces it rather than trusting an argument in the request body.
- Scopes that name capability and audience. "May send utility messages, for tenant X, on channel Y", not "may use the messaging API".
- A revocation path that is not a rotation. Withdrawing one delegation must not disturb any other.
- An audit record carrying the delegation chain, so "who authorised this message?" has a stored answer rather than requiring an investigation.
None of this needs inventing. OAuth 2.0 Token Exchange (RFC 8693) describes how one service obtains a token to act on behalf of another party; JSON Web Tokens (RFC 7519) carry signed, verifiable claims; mutual TLS with certificate-bound tokens (RFC 8705) ties a token to the client presenting it; and workload identity frameworks such as SPIFFE give each service a verifiable identity without shared secrets. Zero-trust guidance such as NIST SP 800-207 describes the same principle at the level of a whole architecture.
What a service credential has to be
- Verifiable
The recipient can check it without calling the issuer. A signature over a known key, not a lookup.
- Scoped
Names the actions and the resources. A credential that says "trusted" says nothing useful.
- Short-lived
Minutes or hours. Expiry is the property that makes compromise survivable without coordination.
- Attributable
Identifies the calling service, not just the fact of authorisation. Logs need a subject.
- Revocable
Independently, by the issuer, without the holder's cooperation. Otherwise trust is permanent.
- Delegable
A can act for B with proof, within B's scope and never beyond it. This is what federation needs.
What to ask a provider#
If you are buying rather than building, these questions reveal how far a platform supports this:
- Can I create credentials scoped to a single sub-account, channel or capability?
- Do you support short-lived tokens, and can I revoke one without rotating the others?
- When a partner or reseller acts on my behalf, does your audit log show which party acted and under what authority?
- Can I see, export and keep those audit logs?
Many platforms support sub-accounts and scoped keys; fewer support delegation with per-customer revocation. Knowing which you are getting avoids surprises.
Why this is worth doing before you need it#
Because it is hard to retrofit. Once integrations exist that assume a long-lived key with implicit authority, every one of them has to change, and each is owned by a different team on a different schedule. The migration is not technically difficult. It is organisationally difficult, and it takes a long time.
The argument against is always the same: we have three services, we know who they are, this is over-engineering.
It may be over-engineering for three services. It is about right for the fourth, which will often be a partner rather than a team, and it is very hard to retrofit for the eleventh, because by then the shared secret is a load-bearing part of several deployment pipelines.
Delegated identity, by the number of integrations
- 1Three services
We know who they are
- 2The fourth
About right — and often a partner rather than a team
- 3The eleventh
The shared secret is load-bearing in several deployment pipelines
The trade-offs#
Short-lived tokens add moving parts: a token service that must be available, clock synchronisation, and more failure modes to monitor. Fine-grained scopes need someone to design and maintain them. For a single company with one backend and one messaging provider, a well-protected, regularly rotated API key with restricted scope may be entirely adequate. The case for delegation grows with every additional party that acts on someone else's behalf.
The federation connection#
If you run several systems that call each other rather than one merged system, this is the layer that makes it safe. Published contracts let systems talk. Service-to-service identity is what makes it defensible when someone asks what a system was allowed to do, for whom, and when that permission ended. Federation without it is a set of shared secrets in configuration files: centralisation with extra steps and none of the isolation it was supposed to buy.
What to take away#
Give every service a verifiable identity. Issue scoped, short-lived, revocable credentials rather than long-lived shared secrets. Make delegation explicit and provable. Do it while the number of integrations is small, because the reason to do it arrives with the first partner and the ease of doing it leaves soon after.
Where to go next#
- Federating systems without merging them: the architecture this identity layer supports.
- Evaluating a CPaaS contract: the contract questions to pair with the technical ones above.
Sources
Every claim worth checking, with somewhere to check it.
- RFC 8693: OAuth 2.0 Token ExchangeIETF
- RFC 7519: JSON Web Token (JWT)IETF
- RFC 8705: OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access TokensIETF
- SPIFFE overviewSPIFFE (Cloud Native Computing Foundation)
- SP 800-207: Zero Trust ArchitectureNIST