Skip to content
Latchkey

step crypto jwt: Sign and Verify JWTs

step crypto jwt sign builds a signed JWT from claims and a key, and step crypto jwt verify checks one against the expected issuer, audience, and key.

When a pipeline needs a JWT for a machine-to-machine call, step crypto jwt avoids writing signing code. It uses JOSE under the hood with clear flags for the standard claims.

What it does

step crypto jwt sign reads claims (from flags or stdin) and signs them with the key from --key using the algorithm in --alg, printing a compact JWT. verify validates the signature and the --iss/--aud/--sub claims, exiting non-zero on any mismatch.

Common usage

Terminal
step crypto jwt sign --key priv.pem --alg ES256 \
  --iss ci --aud api --sub build-123 --exp $(date -d '+5 min' +%s)
# verify
echo "$JWT" | step crypto jwt verify \
  --key pub.pem --iss ci --aud api

Options

FlagWhat it does
--key <file>Signing (sign) or verification (verify) key
--alg <alg>JWS algorithm, e.g. ES256, RS256, HS256
--iss / --aud / --subIssuer, audience, and subject claims
--exp <unix>Expiry as a Unix timestamp
--nbf <unix>Not-before timestamp

In CI

Set --exp to a few minutes out so a leaked token is short-lived. verify checks --iss and --aud, so always pass the values you expect rather than trusting whatever the token carries.

Common errors in CI

"validation failed: square/go-jose: error in cryptographic primitive" means the wrong key or --alg for the token. "invalid audience claim (aud)" or "invalid issuer claim (iss)" means the token's claim does not match what you passed to verify. "token is expired" means --exp already passed; widen the window or re-sign.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →