WIT-SVID (Workload Identity Token)
WIT-SVID is a forward-looking feature and is off by default. Contact Defakto support to enable it for your organization. The token format follows a draft IETF/SPIFFE specification that may still change, so it is not yet recommended for production use.
A JWT-SVID is a bearer token: Anyone who holds it can present it and impersonate the workload. If a JWT-SVID leaks, an attacker can replay it until it expires.
A WIT-SVID closes that gap by being cryptographically bound to a key pair held by the workload. The token embeds the workload's proof-of-possession (PoP) public key in a cnf claim (RFC 7800) and is delivered together with the matching private key. A verifier can require the presenter to prove possession of that private key, so a stolen WIT-SVID alone is not enough to impersonate the workload.
WIT-SVID implements the SPIFFE WIT Workload API profile, built on the IETF WIMSE Workload Identity Token draft.
JWT-SVID compared with WIT-SVID
| JWT-SVID | WIT-SVID | |
|---|---|---|
Token type (typ) | JWT | wit+jwt |
| Bearer or bound? | Bearer | Bound to a PoP key pair |
| Workload receives | Token only | Token and private key |
| Replay protection | None (expiry only) | Proof-of-possession |
aud (audience) | Required | Prohibited |
| Bundle format | JWK Set | JWK Set (keys tagged use: "wit-svid") |
How it works
The Agent generates the proof-of-possession key pair. The workload calls the Workload API and receives both the token and its private key.
Key points:
- The private key never leaves the Agent host until it is handed to your workload, and it is never sent to the Trust Domain Server. The server only sees the public key (in
cnf). FetchWITSVIDis a streaming RPC. Your workload keeps the stream open, and the Agent pushes a new WIT-SVID before the current one expires. This mirrors the X.509-SVID streaming model, and differs from the JWT-SVID model.- The PoP key pair is EC P-256 by default.
What's in a WIT-SVID
A WIT-SVID is a JWS (signed JWT) with these characteristics:
| Claim / header | Value |
|---|---|
typ (header) | wit+jwt |
sub | The workload's SPIFFE ID |
exp, iat | Expiry and issued-at timestamps |
jti | A random ID for log correlation. WIT-SVID verification does not rely on jti for replay protection. |
cnf | { "jwk": <PoP public key> }. The proof-of-possession binding (RFC 7800). |
iss | Omitted. The trust domain is conveyed by sub; WIT-SVIDs deliberately are not OIDC-discoverable. |
aud | Never present. Prohibited by the spec. |
Example decoded payload:
{
"sub": "spiffe://example.org/workload/payments",
"exp": 1750000000,
"iat": 1749996400,
"jti": "a1b2c3d4e5f6...",
"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"alg": "ES256",
"x": "...",
"y": "..."
}
}
}
Signing keys and trust bundles
WIT-SVIDs are signed with a dedicated WIT signing key, separate from the X.509 and JWT signing keys. This allows independent rotation of WIT keys, and keeps the credential types cryptographically isolated. The WIT signing key is provisioned automatically per key set (default EC P-256) and rotated as part of the normal key-set lifecycle.
Verifiers fetch the WIT validation keys through the Workload API's FetchWITBundles RPC, which returns trust bundles as JWK Sets keyed by trust domain. Each WIT key in the set carries use: "wit-svid", which is how clients distinguish WIT authorities from JWT authorities within a unified SPIFFE bundle.