What it is
A command-line tool for inspecting and manipulating JSON Web Tokens (JWTs).
Installation
Linux/macOS (using Homebrew)
brew install jwt-cli
Linux/macOS (using Go modules)
go install github.com/golang-jwt/jwt/v4/cmd/jwt@latest
Make sure your $GOPATH/bin is in your $PATH.
Windows (using Scoop)
scoop install jwt-cli
Windows (using Go modules)
Follow the Linux/macOS Go modules instructions.
Core Concepts
JWTs are commonly used for securely transmitting information between parties as a JSON object. They are typically composed of three parts separated by dots (.):
- Header: Contains metadata about the token, such as the signing algorithm (
alg) and token type (typ). - Payload: Contains the claims, which are statements about an entity (typically, the user) and additional data.
- Signature: Used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed along the way.
The jwt-cli tool allows you to decode these parts, inspect their contents, and even create or sign new tokens.
Commands / Usage
Inspecting JWTs
Decode a JWT (base64url decode header, payload, and signature)
jwt decode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Decodes the JWT and prints the base64url encoded header, payload, and signature parts.
Decode JWT and pretty-print the payload
jwt decode --pretty eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Decodes the JWT and pretty-prints the JSON payload.
Decode JWT and show header and payload
jwt decode --show-header --show-payload eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Decodes the JWT and displays both the header and the payload.
Decode JWT and show only the payload
jwt decode --show-payload eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Decodes the JWT and displays only the payload.
Decode JWT and show only the header
jwt decode --show-header eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Decodes the JWT and displays only the header.
Decode JWT from a file
jwt decode --file ./mytoken.jwt
Decodes a JWT stored in the specified file.
Verify JWT signature (HS256)
jwt decode --secret "your-256-bit-secret" eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o
Verifies the signature of the JWT using the provided secret key. If verification fails, it will exit with an error.
Verify JWT signature (RS256) using public key
jwt decode --public-key ./public.pem eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.abcdefghijklmnopqrstuvwxyz1234567890ABCDEF
Verifies the signature of the JWT using the provided public key file.
Verify JWT signature (ES256) using public key
jwt decode --public-key ./ec_public.pem eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.abcdefghijklmnopqrstuvwxyz1234567890ABCDEF
Verifies the signature of the JWT using the provided EC public key file.
Verify JWT signature (EdDSA) using public key
jwt decode --public-key ./ed_public.pem eyJhbGciOiJFZEdTQSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.abcdefghijklmnopqrstuvwxyz1234567890ABCDEF
Verifies the signature of the JWT using the provided EdDSA public key file.
Creating and Signing JWTs
Create a JWT with a specific payload and HS256 algorithm
jwt create --payload '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}' --secret "your-256-bit-secret" --alg HS256
Creates a new JWT with the specified payload, secret key, and signing algorithm.
Create a JWT with a specific payload and RS256 algorithm using a private key
jwt create --payload '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}' --private-key ./private.pem --alg RS256
Creates a new JWT using the specified private key file and RS256 algorithm.
Create a JWT with a specific payload and ES256 algorithm using an EC private key
jwt create --payload '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}' --private-key ./ec_private.pem --alg ES256
Creates a new JWT using the specified EC private key file and ES256 algorithm.
Create a JWT with a specific payload and EdDSA algorithm using an EdDSA private key
jwt create --payload '{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}' --private-key ./ed_private.pem --alg EdDSA
Creates a new JWT using the specified EdDSA private key file and EdDSA algorithm.
Create a JWT with custom header parameters
jwt create --payload '{"sub": "1234567890"}' --secret "your-secret" --alg HS256 --header '{"kid": "my-key-id"}'
Creates a JWT with a custom kid (key ID) in the header.
Create a JWT and save it to a file
jwt create --payload '{"sub": "1234567890"}' --secret "your-secret" --alg HS256 --output ./new_token.jwt
Creates a JWT and saves the generated token to new_token.jwt.
Other Utilities
Generate a random HS256 secret key
jwt secret --alg HS256
Generates a suitable random secret key for HS256.
Generate a random RS256 private/public key pair
jwt secret --alg RS256
Generates a random RS256 private and public key pair. The private key will be printed to stdout and the public key will be saved to public.pem.
Generate a random ES256 EC private/public key pair
jwt secret --alg ES256
Generates a random ES256 EC private and public key pair. The private key will be printed to stdout and the public key will be saved to ec_public.pem.
Generate a random EdDSA private/public key pair
jwt secret --alg EdDSA
Generates a random EdDSA private and public key pair. The private key will be printed to stdout and the public key will be saved to ed_public.pem.
Convert a PEM private key to PKCS8 format
cat ./private.pem | jwt pem2pkcs8
Converts a PEM-encoded private key to PKCS8 format.
Common Patterns
Inspect a JWT from an HTTP header
echo "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKK924zB0Jc61z4aZJ_G9V1M_j0_1nL_o" | grep -oP 'Bearer \K.*' | jwt decode --pretty
Extracts the JWT from an Authorization: Bearer header and pretty-prints the payload.
Create a JWT and pipe it to a request
NEW_TOKEN=$(jwt create --payload '{"user_id": 123}' --secret "my-super-secret-key" --alg HS256)
curl -H "Authorization: Bearer $NEW_TOKEN" https://api.example.com/data
Creates a new JWT and includes it in the Authorization header of a curl request.
Verify a JWT received from an API using a public key
JWT_FROM_API="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.abcdefghijklmnopqrstuvwxyz1234567890ABCDEF"
jwt decode --public-key ./api_public_key.pem --show-payload $JWT_FROM_API
Verifies a JWT obtained from an API using its public key and displays the payload if valid.
Gotchas
- Secret Key Length: For HS256, the secret key should ideally be 32 bytes (256 bits) or longer for better security. The
jwt secret --alg HS256command generates a suitable key. - Key Format: Public and private keys for asymmetric algorithms (RS256, ES256, EdDSA) must be in PEM format. Ensure they are correctly encoded.
- Algorithm Mismatch: When verifying a token, ensure you use the correct key type (symmetric secret for HS256, private key for signing with RS256/ES256/EdDSA, public key for verification with RS256/ES256/EdDSA) and the corresponding algorithm flag (
--secret,--private-key,--public-key,--alg). - Payload Formatting: The
--payloadargument expects a JSON string. Ensure it’s correctly quoted for your shell. - Expiration (
exp) Claim: JWTs often contain anexpclaim for expiration. Thejwt-cliitself does not automatically validate this claim during decoding unless explicitly programmed to do so by the application using it. You can addexpto your payload when creating tokens. iatClaim: Theiat(issued at) claim is a timestamp. Ensure it’s provided as a Unix epoch time (e.g.,1516239022).