PATTERN Cited by 1 source
Third-party-caveat strip for service token¶
Pattern¶
Design user tokens with a third-party authentication caveat — but for service-token use (tokens stored alongside running code), expose an authority API that:
- Takes the tuple
(permissions-token, discharge-token). - Verifies the discharge (proving the caller could have used the token normally).
- Returns a new token with the third-party authentication caveat removed, and typically with no expiration.
The recipient can then attenuate that token further — binding it to a specific host, instance, or role — before handing it to the service. Theft of the resulting token is useless unless the attacker also controls the environment it's bound to.
Canonical implementation: Fly.io tkdb¶
From sources/2025-03-27-flyio-operationalizing-macaroons:
"The solution we came up with for service tokens is simple:
tkdbexports an API that uses its access to token secrets to strip off the third-party authentication caveat. To call into that API, you have to present a valid discharging authentication token; that is, you have to prove you could already have done whatever the token said.tkdbreturns a new token with all the previous caveats, minus the expiration (you don't usually want service tokens to expire).""OK, so we've managed to transform a tuple
(unscary-token, scary-token)into the new tuple(scary-token). Not so impressive. But hold on: the recipient ofscary-tokencan attenuate it further: we can lock it to a particular instance offlyd, or to a particular Fly Machine. Which means exfiltrating it doesn't do you any good; to use it, you have to control the environment it's intended to be used in."
Properties¶
- Traceability: "every token used in production is traceable in some way to a valid token a user submitted." The strip API requires proof of prior authorization, so the service-token lineage always goes back to a user action.
- No stored authenticator hazmat: running code never holds the auth-service discharge token ("we don't want running code to store those authenticator tokens, because they're hazardous").
- No automatic expiration: service tokens typically don't expire — the binding-by-attenuation is the compensating control.
- Authority-only operation: only
tkdbcan strip (it holds the token secrets). The operation isn't available to bearers in general.
Companion pattern¶
The same third-party-caveat mechanism runs in the other
direction at Fly.io's Pet Semetary secret service — see
patterns/caveat-for-privilege-separation — where a
broadly-privileged read-secret Macaroon carries a third-party
caveat that can only be discharged by proving the right org
permissions through tkdb.
When it applies¶
Any service-token issuance where the token must live next to running code but the auth discharge would be unsafe to store there. Works only if the token construction supports caveat- stripping by the authority (Macaroons do natively because of the chained-HMAC construction — the authority holds the root key and can re-derive).
Seen in¶
- sources/2025-03-27-flyio-operationalizing-macaroons — canonical wiki instance; Fly.io uses this for Fly Machine service tokens and for Pet Semetary secret-reads.