CONCEPT Cited by 1 source
Chained-HMAC construction¶
The chained-HMAC construction is the cryptographic core of Macaroons: a token's integrity tag is an iterative HMAC computation where each caveat added to the token rolls the tag forward by re-HMAC'ing the previous tag with the new caveat's bytes. The final tag is the HMAC of the root key (known only to the authority) chained through every caveat in order.
tag_0 = HMAC(root_key, nonce)
tag_1 = HMAC(tag_0, caveat_1)
tag_2 = HMAC(tag_1, caveat_2)
...
tag_n = HMAC(tag_{n-1}, caveat_n) # on the wire
Two architecturally important properties¶
1. Offline attenuation¶
Because each step's key is the previous tag (not the root key), a caveat can be appended to a token by anyone who holds the current tag — including the bearer, in user space, without contacting the authority. Adding a caveat monotonically reduces the privileges the token can express (the authority checks that every caveat on the chain must hold for any operation to be authorized), so this is safe to delegate to callers. See concepts/attenuation-offline.
2. Descendants inherit verifiability¶
Fly.io's load-bearing cache property:
"Once you've seen and verified a Macaroon, you have enough information to verify any more-specific Macaroon that descends from it; that's a property of their chaining HMAC construction. Our client libraries cache verifications, and the cache ratio for verification is over 98%." (Source: sources/2025-03-27-flyio-operationalizing-macaroons.)
The construction makes verification idempotent under attenuation: to verify a descendant token, replay the tag from the last known-good tag forward by HMAC'ing the additional caveats. You don't need to re-contact the authority or re-derive the root key.
This is why verification caching works so well for Macaroons: the cache key can be the parent tag, and any more-specific descendant is verifiable without a cache miss.
Why this matters at scale¶
- Cache hit rates: >98% at Fly.io's scale. Transoceanic hops to the token authority are avoided in steady state.
- Root-key access scoping. Only the authority holds the root key; every step after that uses tag-as-key. Compromise of a bearer's tag leaks only that specific scope of authority, not root-key-level authority.
- Attenuation is constant-cost. Each added caveat is one HMAC, no network round-trip.
Contrast: JWT signature structure¶
JWTs use a single signature over the entire payload. You cannot attenuate a JWT client-side without invalidating its signature — the signer has to re-issue. That's the core architectural reason Macaroons enable attenuate-on-use and JWTs don't.
Seen in¶
- sources/2025-03-27-flyio-operationalizing-macaroons — canonical wiki instance; Fly.io's 98%+ verification cache hit rate cited explicitly to this property.
Related¶
- concepts/macaroon-token — the token primitive the construction serves.
- concepts/attenuation-offline — the offline-caveat operation the construction enables.
- concepts/verification-cache — the caching pattern that falls out of it.
- systems/macaroon-superfly — the Go implementation.
- companies/flyio.