Summary
For subject: caller_workload, the OAuth delegator runs two IdP calls per
request: leg 1 exchanges the caller's SVID (RFC 7523 client_assertion) for a
base IdP token, and leg 2 exchanges that base token (RFC 8693) for the
downstream-audience-scoped credential. Leg 1's result — the base token — is
independent of the downstream audience and scopes, so it can be reused across
requests (and across multiple downstream targets) until it expires. Today it is
re-minted on every request.
Split out of the PR #131 review as an optimization.
Current behavior
OAuthDelegator::mint_base_token(svid) (leg 1) is called on every
subject: caller_workload delegation, then the existing exchange path (leg 2)
runs on its result. Two round-trips per request, even when the same agent hits the
same or different downstream audiences back-to-back.
Proposed
Cache the leg-1 base token keyed by the calling workload identity (e.g. the
SVID sub / spiffe_id), reused until near expiry. Leg 2 (audience/scope-specific)
stays per-request. A single agent making N downstream calls then costs 1 leg-1 +
N leg-2, not 2N.
Notes / constraints
- Key by the caller principal, not the audience — the base token is
audience-independent, but it is per-agent, so the cache key must carry the
workload identity (mirrors the DelegationKey.workload_id reasoning). Two
different agents must never share a base token.
- Expiry / refresh — re-mint when
now >= expires_at - safety_margin
(same discipline as RawDelegatedToken). The base token's expires_in bounds
reuse.
- Cache scope — per delegator instance is the simplest first cut. A shared /
cross-request cache would need the same care as the delegated-token cache
(per-principal keying is the precondition already established).
- Security — the base token is a real credential; store zeroized, cap the
cache, and never key it in a way that lets one agent be served another's.
Acceptance criteria
References
Summary
For
subject: caller_workload, the OAuth delegator runs two IdP calls perrequest: leg 1 exchanges the caller's SVID (RFC 7523
client_assertion) for abase IdP token, and leg 2 exchanges that base token (RFC 8693) for the
downstream-audience-scoped credential. Leg 1's result — the base token — is
independent of the downstream audience and scopes, so it can be reused across
requests (and across multiple downstream targets) until it expires. Today it is
re-minted on every request.
Split out of the PR #131 review as an optimization.
Current behavior
OAuthDelegator::mint_base_token(svid)(leg 1) is called on everysubject: caller_workloaddelegation, then the existing exchange path (leg 2)runs on its result. Two round-trips per request, even when the same agent hits the
same or different downstream audiences back-to-back.
Proposed
Cache the leg-1 base token keyed by the calling workload identity (e.g. the
SVID
sub/spiffe_id), reused until near expiry. Leg 2 (audience/scope-specific)stays per-request. A single agent making N downstream calls then costs 1 leg-1 +
N leg-2, not 2N.
Notes / constraints
audience-independent, but it is per-agent, so the cache key must carry the
workload identity (mirrors the
DelegationKey.workload_idreasoning). Twodifferent agents must never share a base token.
now >= expires_at - safety_margin(same discipline as
RawDelegatedToken). The base token'sexpires_inboundsreuse.
cross-request cache would need the same care as the delegated-token cache
(per-principal keying is the precondition already established).
cache, and never key it in a way that lets one agent be served another's.
Acceptance criteria
References
delegator-oauth,mint_base_token).