Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Token & claims spec

The token is the contract between your platform and Warden. This is its shape. Warden accepts either a compact JWT (production) or a dev envelope (local).

Claims

{
  "iss": "https://idp.example.com",
  "aud": "warden:prod",
  "exp": 1893456000,
  "nbf": 1893452400,
  "iat": 1893452400,
  "jti": "tok_abc123",

  "sub": "alice@example.com",
  "act": { "sub": "svc-principal", "act": { "sub": "prod-agent" } },

  "roles": ["analyst"],
  "attrs": { "region": "EU", "team": "research" },
  "rel":   [ { "relation": "can_read", "resource": "table:sales" } ],
  "scope": ["query_table", "read_records"],
  "resource_attrs": { "table:sales": { "classification": "public" } },

  "cnf": { "jkt": "<DPoP JWK SHA-256 thumbprint>" }
}
ClaimRequiredMeaning
subAccountable human. Empty ⇒ fail closed.
actDelegation chain; the deepest sub must equal --agent.
audwhen --aud setAudience; must match.
isswhen --iss setIssuer; must be in the allowlist.
exp / nbfexp in JWT modeValidity window (with --leeway).
jtirecommendedToken id; used for revocation and audit.
rolesRBAC roles.
attrsABAC attributes (subject: conditions).
relReBAC tuples {relation, resource}.
scopeDelegated tool grant (scope narrowing).
resource_attrsTrusted per-resource attributes (resource: conditions).
cnf.jktDPoP proof-key thumbprint (RFC 7800/9449).

Verification rules

  • Algorithm — asymmetric only (RS*, PS*, ES*, EdDSA). HMAC and none are rejected (blocks the RS256→HS256 downgrade).
  • Key source — JWKS (by kid, file or HTTPS with cache/rotation), OIDC discovery, or a PEM public key.
  • Accountability — non-empty sub; the leaf actor of act must equal the agent on the wire.
  • Freshnessexp/nbf with leeway; session tokens are re-validated (and refreshed-or-denied) per action.

Dev envelope (local only)

{
  "claims": { "sub": "alice@example.com", "act": { "sub": "prod-agent" }, "aud": "warden:test" },
  "sig": "<sha256_hex('KEY|' + canonical_json(claims))>"
}

Verified with --token-key KEY. With no key it’s an unsigned dev token (signed = false). Never an enforcement mode.

Produce & verify

Build tokens with the Python SDK (TokenBuilder, identity adapters, JwtSigner), and verify any token the way the proxy does:

warden token verify --token FILE --agent NAME --aud AUD \
  (--jwks-url URL | --issuer-key PEM | --token-key KEY)

The proxy always accepts a raw conforming token with no SDK — this spec is the interface.