Skip to main content

Kubernetes workloads (SPIFFE)

Time: ~20 minutes (plus SPIRE, if your cluster doesn't run it yet). The strongest machine credential is no credential: the SPIRE agent on the node attests your pod and issues it a short-lived (~5 min) JWT-SVID; AuthSec verifies it against your registered trust domain. Nothing stored, nothing to leak, nothing to rotate.

How a pod gets a token:

  1. The pod asks the local SPIRE agent (unix socket) for a JWT-SVID.
  2. The SDK presents the SVID as its client assertion at the token endpoint.
  3. AuthSec verifies it against your trust domain's OIDC discovery endpoint — the workload identity provider you register below.
  4. Out comes a scoped access token, same as every other method.

Setup is three parts: your cluster (once), the trust registration (once), and the workload connection (per application).

Prerequisites — SPIRE in your cluster

You need a running SPIRE deployment with the OIDC discovery endpoint exposed at a public URL, a registration entry for your pod, and the agent socket mounted into the pod. This is standard SPIFFE infrastructure — the official quickstart covers it, and the SDK guide lists the exact registration entry and pod-spec volume mount.

Step 1 — Register the trust domain (once)

Sidebar → SETTINGS → Trusted IssuersWorkload identity providers — issuers your workloads authenticate with: SPIRE trust domains (any cluster) and OIDC federation (e.g. GitHub Actions). No secrets. Click + Add provider:

Workload identity providers

Add workload identity provider

  • Name — a label, e.g. prod-spire
  • KindSPIRE (SPIFFE)
  • Issuer URL — your SPIRE OIDC discovery URL
  • Trust domain — your SPIFFE trust domain, e.g. authsec.local
  • Allowed audiences — leave empty; it defaults to this token endpoint, which is exactly what SVIDs must be minted for

Step 2 — Connect the workload to your application

Open the application → Access tab → Add accessKubernetes workload, no secret:

Add access — Kubernetes workload

A four-step wizard opens:

Workload — choose AuthSec-managed (AuthSec mints the SPIFFE ID for you) or Bring your own SPIRE (federates the trust domain from step 1), and name the workload:

Connect Kubernetes workload — step 1

Access — pick the role this workload holds on the application (the roles from Access policy):

Connect Kubernetes workload — step 2, role

Trust — select your registered provider and paste the exact SPIFFE ID from your SPIRE registration entry (spiffe://your-trust-domain/ns/prod/sa/api). It must match the SVID's sub exactly, and its trust domain must match the selected provider. Click Register workload:

Connect Kubernetes workload — step 3, trust

Install — the confirmation screen is your pod's contract; read it closely:

Connect Kubernetes workload — step 4, install

  • SPIFFE ID — the identity the pod presents instead of any secret
  • SVID audience — must be minted for the token endpoint (https://mcpauthz.com/oauth/token) exactly, or the exchange is rejected
  • Install snippet — a ready-made spire-server entry create command (fill in your namespace / service-account selectors)

Click Done — the workload appears in the app's Who has access list as an active machine identity with its role and effective scopes.

Step 3 — Code inside the pod

The SDK fetches and renews SVIDs automatically from the agent socket:

from authsec_sdk import SpiffeWorkloadIdentity, SpiffeConfig

spiffe = SpiffeWorkloadIdentity(SpiffeConfig(
mcp_server_url=MCP_URL,
client_id=SPIFFE_CLIENT_ID, # from the Install screen
spiffe_id="spiffe://your-domain/your-workload",
scopes=["my_mcp:read"],
))
async with spiffe:
token = await spiffe.access_for()

Testing with a manually minted SVID, low-level auth class, and the two hard-won audience/expiry rules: Python SDK — Kubernetes / SPIFFE.

Troubleshooting

ErrorCauseFix
invalid_client: token aud must include this token endpointSVID minted with the wrong audienceMint with -audience https://mcpauthz.com/oauth/token
invalid_client: … token is expiredJWT-SVIDs live ~5 minutesMint right before use, or use SpiffeWorkloadIdentity (auto-renews)
Exchange rejected despite correct audienceSPIFFE ID doesn't match the SVID's sub, or trust domain mismatchRe-check step 2's Trust screen against your SPIRE registration entry

Next

Machines are connected. The other kind of caller acts for a person:

→ ID-JAG agents