Biscuit Tokens

Bulwark uses Biscuit tokens for agent authentication — a modern, unforgeable token format that supports cryptographic delegation.

Why Not JWT for Agents?

JWTs work well for human sessions, but have a key weakness for agents: they cannot be safely delegated. If agent A delegates to agent B, there's no way to constrain what B can do with a JWT — B could present the full token anywhere.

Biscuit tokens solve this through attenuation: a holder can create a new token with equal or reduced permissions, but can never escalate privileges.

Token Structure

A Biscuit token is a chain of signed blocks:

Block 0 (Authority — signed by Bulwark)
  check if right("read:customers")
  check if time($t), $t <= 2026-03-18T14:00:00Z

Block 1 (Attenuation — signed by agent)
  check if resource($r), $r == "customer:cust_abc"

Each block adds caveats (restrictions). Removing caveats is cryptographically impossible.

Datalog Policy Language

Biscuit uses a Datalog-like language to express authorization policies:

// Authority block (issued by Bulwark)
right("read:customers");
right("write:tickets");
valid_agent("agent_01j");
expiry(2026-03-18T14:00:00Z);

// Check that the agent is valid and not expired
check if valid_agent($id), expiry($t), time($now), $now <= $t;

Attenuation in Practice

// Agent A receives a Biscuit from Bulwark with broad scopes
const agentToken = session.credentialToken;

// Agent A attenuates for sub-agent B
const subToken = await session.attenuate({
  scopes: ["read:customers"],         // subset only
  ttl: 300,                           // 5 minutes
  caveats: [
    { type: "resource", value: "customer:cust_abc" } // specific resource
  ],
});

// Sub-agent B cannot:
// - Remove the resource caveat
// - Extend the expiry
// - Add scopes it doesn't have
// - Use the token after 5 minutes

Verification

Bulwark verifies Biscuit tokens at the API gateway:

  1. Signature chain — each block must be validly signed
  2. Datalog evaluation — all checks must pass
  3. Time check — token must not be expired
  4. Revocation check — token root must not be revoked
  5. Scope check — requested operation must be within granted scopes

Vs. Macaroons

Biscuit tokens are similar to macaroons but improve on them:

| Feature | Macaroon | Biscuit | |---------|----------|---------| | Attenuation | Yes | Yes | | Offline verification | Partial | Yes | | Policy language | HMAC caveats | Datalog (expressive) | | Signature scheme | HMAC | Ed25519 (public key) | | Third-party caveats | Yes | Yes |

The public key signature means Bulwark's public key can be distributed — any service can verify a Biscuit without calling back to Bulwark.