Module 3 · Cryptographic delegation
Signed short-lived credentials
A short-lived credential is a signed grant that expires quickly (seconds to minutes), is bound to a specific audience and purpose, and is minted at the moment of need rather than held indefinitely. Short TTLs make expiry the primary safety control, shrinking the window a leaked credential is useful and reducing dependence on revocation infrastructure that is hard to make timely and reliable.
Learning objective
Understand why short-lived, narrowly-scoped signed credentials — bound to an audience and purpose and issued just in time — are usually safer than long-lived credentials backed by revocation lists.
- Track
- Engineering
- Module
- 3 · Cryptographic delegation
- Prerequisites
- Digital signatures · Scope attenuation
Conceptual introduction
There are two broad ways to limit the damage a credential can do if it leaks. One is to issue it long-lived and keep a list of credentials you have decided to revoke, checking that list on every use. The other is to issue it short-lived, so it simply stops working on its own a few minutes later. The second approach moves the hard problem — "make sure everyone learns this credential is now invalid, right now" — into the much easier one — "make sure clocks roughly agree and set a tight expiry."
Short-lived credentials pair naturally with just-in-time issuance: rather than handing an agent a durable token at startup, you mint a fresh, narrow token at the moment it needs to act, for exactly that action, and let it expire straight after. The credential is a brief permission slip, not a standing key to the building.
Short TTL turns expiry into the default revocation. A ten-minute token that leaks is dangerous for at most ten minutes; a one-year token that leaks is dangerous until you successfully propagate a revocation everywhere it is checked.
Technical foundation
A signed short-lived credential binds, at minimum: the subject/holder, the scope (which resources and operations — attenuated to the task), an audience (who is allowed to accept it), a purpose, an issued-at and a near expiry, and a signature over all of it. Audience and purpose binding are what stop a token issued for one service being replayed at another. This shape is the same one used by short-lived access tokens in OAuth 2.0 / OpenID Connect deployments and by cloud "security token service" credentials, where durable secrets stay at the issuer and only brief, scoped tokens travel.
- TTL (time to live)
- How long the credential is valid after issuance. "Short-lived" typically means seconds to a few minutes.
- Audience binding (aud)
- Naming which verifier(s) may accept the credential, so a token for service X is rejected by service Y.
- Purpose binding
- Restricting the credential to a specific intent/operation, so it cannot be repurposed for a different action within the same service.
- Just-in-time (JIT) issuance
- Minting the credential at the moment of need for exactly that action, rather than holding a standing credential.
- Revocation list
- A maintained set of credentials declared invalid before their natural expiry, which verifiers must consult — the thing short TTLs reduce reliance on.
The model: short-lived vs long-lived + revocation
The two designs differ in where the risk lives. Long-lived + revocation keeps the exposure window open until a revocation is both decided and propagated to every verifier — a distributed-systems problem with real latency and failure modes. Short-lived keeps the window bounded by the TTL regardless of whether anyone noticed the leak.
the two models, compared (schematic)# Long-lived credential + revocation list cred = sign(issuer, {sub, scope, exp=+365d}) # verifier on every use: if is_revoked(cred.id): # must query/replicate a fresh deny-list reject() # exposure window = time to DETECT + PROPAGATE revocation # leak before you revoke -> usable for up to a year # Short-lived, just-in-time, audience+purpose bound cred = sign(issuer, {sub, scope, aud="svc-reports", purpose="summarize", iat=now, exp=now+5m}) # verifier on every use: if now > cred.exp: reject() # expiry is local, needs no network if cred.aud != self.id: reject() # can't be replayed at another service if request.purpose != cred.purpose: reject() # leak -> usable for at most 5 minutes, only at svc-reports, only to summarize
Neither model removes the need for good key custody or binding; the point is that short TTL makes the common failure (a credential ends up somewhere it should not) self-correcting without a perfectly reliable, perfectly timely revocation channel.
Step by step: issuing a just-in-time credential
- 1The agent reaches a point where it needs to perform a specific action against a specific service.
- 2It requests a credential from the issuer, stating the exact scope, the target audience, and the purpose.
- 3The issuer authenticates the request, attenuates the scope to the minimum, and signs a credential with a short TTL (and iat).
- 4The agent presents the credential to the target service for that one action.
- 5The verifier checks the signature, that now is within [iat, exp], that aud matches itself, and that the request matches the bound purpose/scope — all locally, no deny-list round trip.
- 6The credential expires shortly after; the next action requires a fresh issuance.
Synthetic example
synthetic — a JIT credential and a replay attempt# Agent needs to read one report from the reports service, once. req = { scope: "read vault:A/reports/q3.pdf", aud: "svc-reports", purpose: "summarize-q3" } cred = sign(issuer_key, { sub: "agent-7.pub", scope: "read vault:A/reports/q3.pdf", aud: "svc-reports", purpose: "summarize-q3", iat: 1700000000, exp: 1700000300 # +5 minutes }) # svc-reports verifies locally and serves the file. 6 minutes later: # attacker replays the SAME cred -> now > exp -> REJECT (expired) # attacker replays at svc-billing -> aud != "svc-billing" -> REJECT # attacker reuses it to DELETE -> scope has only read / purpose mismatch -> REJECT
The credential was powerful for exactly one narrow action for five minutes at one service, and then became inert on its own. No revocation message had to travel anywhere for that to be true.
Application to agents
Agents are long-running, call many services, and are exposed to untrusted input — exactly the conditions where a standing, broad credential is most dangerous. Just-in-time, short-lived, purpose-bound credentials fit the agent lifecycle: each tool call gets a fresh token scoped to that call, bound to that tool, valid for the length of that call. A prompt-injected instruction that extracts a token gains something that expires in minutes, works only at one service, and only for one purpose — a far smaller prize than a durable key.
This also composes cleanly with delegation chains and attenuation: each hop can mint short-lived child credentials for its sub-agents, so authority both narrows (attenuation) and decays (TTL) as it flows outward. Audience binding additionally blocks a whole class of confused-deputy and token-redirection attacks, because a token simply will not be accepted by a service it was not minted for.
A short-lived credential limits exposure; it does not validate intent. A freshly minted, correctly bound token still authorizes whatever action an injected or mistaken agent decides to take within its scope during its brief life. Short TTL shrinks blast radius — it does not make the decision correct.
Risks & limitations
- ▸Clock skew breaks TTLs: verifiers and issuers need roughly synchronized clocks, and you need a small leeway plus a plan for badly-skewed clients. Too-tight TTLs can cause spurious rejections.
- ▸Short TTLs shift load to the issuer, which becomes a high-rate, high-value dependency and a potential bottleneck or single point of failure; it needs to be available and well protected.
- ▸Short TTL is not instant revocation. Within the TTL a leaked token still works — for high-stakes actions you may still need an additional explicit revocation or step-up check.
- ▸Binding must be enforced: if a verifier ignores aud or purpose, you lose the replay protection those fields were supposed to provide. Unknown or missing bindings must fail closed.
- ▸Issuing credentials that are short-lived but still too broad in scope only limits time, not blast radius — pair short TTL with tight attenuation.
- ▸A valid, unexpired, correctly-bound credential proves authority for now; it never proves the authorized action is the right thing to do.
Exercise
A team proposes replacing their one-year API keys with ten-minute signed tokens bound to an audience and purpose, minted just in time. Give two concrete security advantages this provides over "one-year key + revocation list", and two new operational concerns the team must now handle.
Expected direction: Advantages: (1) a leaked token is usable for at most ten minutes instead of up to a year, so exposure is bounded without needing to detect-and-propagate a revocation; (2) audience+purpose binding stops the token being replayed at a different service or for a different action, closing redirection/confused-deputy replays. New concerns: (1) clock synchronization/skew between issuer and verifiers, with leeway and handling for skewed clients; (2) the issuer becomes a high-rate, high-value, always-needed dependency that must be highly available and strongly protected (also: for some high-stakes actions, short TTL still is not instant revocation).
Check your understanding
- Why can short TTLs reduce reliance on revocation lists?
- Because the credential expires on its own quickly, bounding the exposure window locally without needing a revocation decision to be detected and propagated to every verifier in time.
- What do audience and purpose binding prevent?
- Replay/redirection: a token minted for one service and one action is rejected by other services and for other actions, closing a class of confused-deputy and token-reuse attacks.
- Name one real operational cost of moving to short-lived JIT credentials.
- Dependence on clock synchronization (skew can cause spurious rejections) and/or increased load on and criticality of the issuer, which becomes an always-needed, high-value service.
References
- [1]Hardt (ed.) — The OAuth 2.0 Authorization Framework (RFC 6749)
- [2]Jones, Bradley, Sakimura — JSON Web Token (JWT) (RFC 7519)
- [3]Jones, Campbell et al. — JWT Best Current Practices (RFC 8725)
References point to public, well-known technical sources for further study.
Related articles
