RepoAnthropicAnthropicpublished Aug 18, 2026seen 11h

anthropics/claude-tag-wif-gateway-sample

Python

Open original ↗

Captured source

source ↗

anthropics/claude-tag-wif-gateway-sample

Description: Sample customer-side gateway for Claude Tag identity federation. Sample code; not maintained.

Language: Python

License: Apache-2.0

Stars: 0

Forks: 0

Open issues: 0

Created: 2026-08-18T13:49:20Z

Pushed: 2026-08-28T03:43:49Z

Default branch: main

Fork: no

Archived: no

README:

Claude Tag Custom Gateway — Sample Implementation

Sample code. Not maintained and not accepting contributions. This is a reference implementation of the "custom gateway" described in the Claude Tag Identity Federation onboarding guide (Chapter 2, "Custom endpoint — direct token presentation"). The Claude Tag identity federation feature is currently in private beta; your Anthropic contact can tell you whether it is available to your organization. This code is meant to be read, adapted, and reviewed against your own security requirements before any production use. It is not a supported product.

What it does

Anthropic calls your registered endpoint directly, attaching a Claude Tag identity token to each request in the Authorization header as a bearer token. This gateway:

1. Validates every incoming token — signature (ES256, against the issuer's published JWKS), exact issuer, your registered audience, and expiry. Anything that fails is rejected with a generic 401. 2. Maps the verified claims to a principal in your system, from a config file — exact-match on the token subject (preferred), with a channel_id-based mapping shown as an alternative. 3. Serves a discovery route (GET /list-services) so the agent can learn at runtime what this gateway offers — one useful pattern for making a gateway discoverable to the model. 4. Answers a readiness probe at the root (GET / or POST /) that only confirms the caller's token is valid and maps to a principal. 5. Proxies requests to mapped downstream services (/services/{name}/...), injecting a downstream credential from an environment variable. The Claude Tag token itself is never forwarded downstream.

Layout

gateway/constants.py Issuer URL, discovery URL, algorithm allowlist, subject prefix
gateway/jwks.py OIDC discovery -> jwks_uri -> key cache, refresh on unknown kid
gateway/auth.py Bearer extraction and the four verify checks from the guide
gateway/mapping.py Config-file claims -> principal -> allowed services
gateway/main.py App factory, / readiness, /list-services, /services/{name}/{path} proxy
config.example.yaml Example mapping config with deliberately fake IDs, plus the
reserved registration-test control subject
tests/ Offline test harness with locally generated throwaway keys

Quickstart

python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest # all tests run offline, no Anthropic dependency
cp config.example.yaml config.yaml # then edit with your real values
.venv/bin/python -m uvicorn gateway.main:create_app --factory --port 8000

Or with Docker:

docker build -t claude-tag-gateway-sample .
docker run -p 8000:8000 \
-v "$PWD/config.yaml:/app/config.yaml:ro" \
-e EXAMPLE_API_TOKEN=... \
claude-tag-gateway-sample

How this maps to the onboarding guide

Follow the guide's Chapter 2 steps with this code side by side.

Step 1 — Choose an audience value and register your endpoint

Pick your audience string (printable ASCII, no spaces, at most 256 bytes; values used for cloud token exchange such as sts.amazonaws.com are reserved). Put it in config.yaml under audience, and send it with your endpoint URL to your Anthropic contact for registration. If your organization has access to self-serve registration, you register there instead and can run the registration test described under "The readiness route and the registration test" below. If you plan to run that test, use your gateway's https root URL, with no path or query string, as the audience: with any other audience the registration call fails unless you explicitly skip the test.

Step 2 — Validate tokens at your endpoint

gateway/auth.py and gateway/jwks.py implement the guide's four checks:

  • Signature — keys are fetched from the jwks_uri named in the

discovery document at https://identity.anthropic.com/claude-tag/.well-known/openid-configuration. Only ES256 is accepted. On an unknown key id the key cache refreshes once before rejecting, which absorbs key rotation (this is the guide's troubleshooting advice, implemented).

  • Issuer — exactly https://identity.anthropic.com/claude-tag.
  • Audience — the value you registered. On the wire the audience claim

is a JSON array with one element, which is standard JWT; the code uses the library's audience check rather than comparing raw claim text, as the guide recommends.

  • Expiry — tokens live 10 minutes; no leeway is granted.

The test suite (tests/) is the guide's step 2.3 made runnable: it mints tokens with locally generated throwaway keys and verifies the gateway rejects wrong-audience, bad-signature, and expired tokens (plus wrong issuer, alg=none, unknown key id, and missing claims) and accepts a valid token against a local JWKS. Everything runs offline.

Step 3 — Map subjects to principals

The token subject identifies one agent: wimse://identity.anthropic.com/org//agent/. Your Anthropic contact provides your organization ID (starts with org_) and each agent's ID (starts with cagt_). Put exact-match entries in config.yaml under principals. A channel_id-keyed mapping is shown under channel_principals — a custom endpoint can authorize on any claim because it verifies the full token itself, but a channel mapping is broader than a subject pin, so prefer subject pins.

Channel lifecycle caveat (from the guide): an agent's identity is tied to its channel. Deleting and recreating a channel — even with the same name — creates a new agent with a new subject, and pinned mappings stop matching with no other warning. If that happens, get the new subject from your Anthropic contact and update config.yaml.

Step 4 — Submit for review and verify end to end (required)

Anthropic reviews every connection configuration in this beta before enabling it. Send your Anthropic contact: your audience value, where validation happens, and how subjects map to permissions. The connection is not enabled until that review is done. After enablement, trigger a test action from the agent's channel and check your gateway's logs — token...

Excerpt shown — open the source for the full document.