Passports
Shared secrets and long-lived API keys leak, and token introspection puts a network call in every request path. A TrustPlane Passport solves both problems: it is a short-lived, audience-scoped, proof-bound authorization artifact. Issuing one turns a workload identity into something a verifier can check; verifying one confirms its signature and claims against local public trust material — no shared secret, no mandatory network call.
How it works
Section titled “How it works”- Issuing is done by
trustplane issue(CLI), thetrustplane-issuerbinary, or the broker. - Verification lives in
pkg/authcore: it resolves the issuer key, checks the signature, and validatesiss,sub,aud,iat,exp,jti,trust_domain, andcnf. - Keys are resolved from a TrustPlane bundle document, so verification is offline-capable.
The verification steps (from authcore):
flowchart LR P["Passport"] --> K["Resolve issuer key from bundle"] K --> S["Verify signature"] S --> CL["Validate iss/sub/aud/iat/exp/jti/trust_domain/cnf"] CL --> AUD["Check expected audience + trust domain"] AUD --> CNF["Check cnf (request proof binding)"] CNF --> RP["Replay/jti check (if enabled)"] RP --> R["allow / deny + reason"]
Issue and verify a passport
Section titled “Issue and verify a passport”Issue a passport and write a trust bundle containing its public key:
./bin/trustplane issue \ --subject spiffe://example.local/ns/default/sa/demo \ --audience example-api \ --trust-domain example.local \ --bundle-out trustplane-bundle.jsonVerify with an explicit public key:
./bin/trustplane verify \ --token "$TOKEN" \ --public-key "$PUBLIC_KEY" \ --kid "$KEY_ID" \ --issuer "$ISSUER" \ --audience example-api \ --trust-domain example.local…or verify against the bundle (the offline-friendly path):
./bin/trustplane verify \ --token "$TOKEN" \ --bundle trustplane-bundle.json \ --kid "$KEY_ID" \ --issuer "$ISSUER" \ --audience example-api \ --trust-domain example.localRun the bundled demo (issues + verifies + runs the protected-service example):
make demoWhat to notice
Section titled “What to notice”- The verifier consumed only public material (the bundle). The private key never left the issuer.
- Change
--audienceon verify and it fails — the passport is audience-scoped, not a general-purpose token. - A passport alone is not enough to call a protected route; it must be paired with request
binding so the verifier can confirm the caller holds the
cnfkey for this request.
Next steps
Section titled “Next steps”- Request binding — bind a passport to the exact request it authorizes.