Token Vault
Architecture

Architecture: Two Planes, Zero Custody

The canonical explanation of Token Vault's webhook-sovereign design — control plane vs data plane, signed-ticket credential paths, encryption custody, and the kill switch.

This page is the one full telling of how Token Vault works. Every other page links here instead of re-explaining it.

Token Vault is a webhook-sovereign architecture split into two planes with strictly separated responsibilities:

PlaneWhereHoldsTouches credentials?
Control planeToken Vault (Cloud Run, api.tokenvault.uk)identities, grants, policies, audit metadata, webhook URL + HMAC secretNo
Data planeYour webhook (Cloudflare Workers / Cloud Run / Lambda / Deno)credentials, encryption key, OAuth refreshYes — this is the custodian

Token Vault's security property is absence: credential bytes never cross it. It does not receive credentials, does not store them, does not encrypt or decrypt them, and holds no key that could ever do so. In every path below, its transcript is the same: validate → sign ticket → step aside.

Loading diagram...

The three credential paths

1. Agent retrieval (307 redirect). The agent sends GET /api/agents/credentials?service=github with its tvagent_… key. Token Vault validates the key, checks the grant, and evaluates ABAC policies — then signs an HMAC-SHA256 ticket and answers with a 307 redirect to your webhook's /v1/credential. The agent's HTTP client follows the redirect and receives the credential directly from your webhook. Full request/response detail: API Reference → Agent Credentials.

2. Storing (browser-direct). When you add a token in the dashboard, Token Vault issues a signed store ticket and the browser sends the credential straight to your webhook's /v1/store. The ticket proves authorization; the bytes go browser → webhook.

3. MCP proxy (server-side injection). The agent calls the proxy with an mcp_… key. Token Vault authenticates, policy-checks, and forwards the request to your webhook's /v1/proxy with a signed ticket. Your webhook injects the credential into the upstream request and calls the upstream itself. Token Vault relays the upstream response but never the credential. Detail: API Reference → MCP Proxy.

Refresh follows the same custody rules — by default your webhook refreshes OAuth tokens autonomously and no credential material crosses Token Vault. The one narrow opt-in exception is documented in API Reference → Token Refresh.

Custody and encryption

Encryption at rest is your webhook's decision, not Token Vault's guarantee. Token Vault cannot see — let alone enforce — what your webhook does with a credential after it arrives. The reference implementations encrypt every sensitive field with AES-256-GCM (authenticated encryption, tamper detected on decrypt); metadata stays plaintext so the dashboard can list tokens without a decrypt call.

Encrypted token document (reference implementation)
{
  "v": 1,
  "alg": "AES-256-GCM",
  "fields": {
    "accessToken": "<base64(12B-iv || ciphertext || 16B-tag)>",
    "refreshToken": "<base64(12B-iv || ciphertext || 16B-tag)>"
  },
  "meta": {
    "serviceName": "github",
    "tokenType": "JWT",
    "createdAt": "2026-02-01T10:00:00Z",
    "expiryTime": 1720003600000,
    "hasRefreshToken": true
  }
}
ParameterValue
Key32 bytes (256-bit), generated and held by the webhook
IV12 bytes, random per encryption, prepended to ciphertext
Tag16 bytes, appended by AES-GCM
AADNone

Your webhook, your rules

A webhook that stores credentials in plaintext is still a conformant webhook — Token Vault can't tell the difference and never claims otherwise. Encrypting at rest is strongly recommended, and every reference implementation does it.

The dashboard shows a trust badge on each token card: TV Zero (green) for tokens Token Vault never touches in any flow, and TV Refresh (blue) for tokens where the webhook has opted in to TV-mediated refresh (in transit only, never stored).

The kill switch

Taking your webhook offline instantly locks the vault — Token Vault cannot hand out anything, because the credentials exist only on your webhook:

  • All agent redirect requests fail (webhook unreachable).
  • All MCP proxy requests return 503.
  • Token refresh stops.
  • Bring the webhook back online and everything resumes.

This is the emergency revocation mechanism — no action needed from Token Vault, and nothing Token Vault (or an attacker who compromised it) could do to bypass it. You can go further and firewall Token Vault's static egress IP; see Webhook Security.

Next Step

Bind your webhook → — the one-time handshake that pairs a deployed webhook with your Token Vault account. Or jump straight to the Quickstart.

Ready to try it?

Sign up free with Google — your credentials stay on your own webhook, and the quickstart gets an agent fetching its first credential in about ten minutes.

On this page