Examples (and Benchmarks)
May 14, 2026 · View on GitHub
Runnable usage patterns for github.com/lestrrat-go/jwx/v4 and its companion modules. Every file in this repo is a single Example_* test function with extensive inline comments — read them as documentation, run them with go test.
Build/run requires GOEXPERIMENT=jsonv2 (jwx v4 depends on encoding/json/v2).
Per-package entry points
Start here if you want a representative overview of a package:
github.com/lestrrat-go/jwx/v4— library-wide operationsgithub.com/lestrrat-go/jwx/v4/jwtgithub.com/lestrrat-go/jwx/v4/jwsgithub.com/lestrrat-go/jwx/v4/jwegithub.com/lestrrat-go/jwx/v4/jwk
The topical index below lists every example file by purpose. Filenames follow <package>_<action>_example_test.go.
JWT — tokens, claims, validation
Constructing
- Builder pattern —
jwt.NewBuilder()to assemble standard claims - Direct construction —
jwt.New()+Set()for full control - Get claims — typed accessors (
Expiration,Audience, …) andFieldfor private claims - Raw struct usage — back-channel between
jwt.Tokenand your own Go types
Parsing / verifying
- Parse (basic) — minimal verify+validate flow
- Parse with key — explicit single-key verification
- Parse with key set —
kid-based selection from a JWK Set - Parse with key provider — programmatic key resolution
- Parse via
jkuheader — fetch keys from the URL in the JWS header (whitelist required) - Parse from
*http.Request— pull token out of the Authorization header / cookie / form - Parse from filesystem —
jwt.ParseFSfor fs.FS-backed tokens
Validating
- Validate (basic) — standalone claim checks on an already-parsed Token
- Validate issuer —
jwt.WithIssuer - Custom validator — implement
jwt.Validatorfor app-specific checks - Pass request context —
jwt.WithContextthreads acontext.Contextinto custom validators - Detect error types — distinguish parse vs. validation failures with
errors.Is
Signing / serialization
- Sign with custom base64 — swap the base64 backend per call
- Serialize as JWS — sign and emit a compact JWS-wrapped JWT
- Serialize as nested JWE+JWS — sign then encrypt
- Serialize as JSON — raw JSON form (no signature)
- Flatten
aud— single-string vs. array form
Filtering claims
- Basic filter — restrict a token to a claim allowlist
- Advanced filter — predicate-driven filtering
JWS — sign and verify arbitrary payloads
Signing
- Sign (basic) — payload + key + algorithm
- Sign with headers — attach
kid,typ, etc. to the protected header - Sign as JSON serialization — multi-signature JSON form
- Sign detached payload — RFC 7797 detached form
- Sign detached payload (streaming) —
jws.WithDetachedPayloadReaderfor large payloads from anio.Reader - Sign with
crypto.Signer— HSM / KMS-backed signers - Sign with ES256K (secp256k1) — extension module required
- Sign with Ed448 — extension module required
- Sign with custom base64
- Custom signer / verifier — plug in a new algorithm
Verifying / parsing
- Verify with key
- Verify with key set
- Verify detached payload
- Verify detached payload (streaming) —
jws.WithDetachedPayloadReaderfor large payloads from anio.Reader - Verify with
critopt-out — handle unknown critical headers - Parse (structure only) — does NOT verify
- Parse from filesystem
- Access JWS header on a JWT
Filtering headers
JWE — encrypt and decrypt arbitrary payloads
Encrypting
- Encrypt (basic) — single recipient, compact form
- Encrypt with headers — protected and per-recipient headers
- Encrypt to multiple recipients (JSON) —
jwe.WithJSON()+ multiplejwe.WithKey(...) - Encrypt with ECDH-ES (X25519)
- Encrypt with HPKE — overview
- HPKE with X25519
- HPKE-5-KE — AES-256-GCM mode
- HPKE-6-KE — ChaCha20Poly1305 mode
Decrypting / parsing
- Decrypt with key
- Decrypt with key set
- Parse (structure only) — does NOT decrypt
- Parse from filesystem
Filtering headers
JWK — keys and key sets
Parsing
- Parse a single JWK —
jwk.ParseKey[jwk.Key] - Parse a JWK Set —
jwk.Parse - Parse from PEM — convert PEM-encoded crypto.* keys to
jwk.Key - Parse from filesystem
- Parse PEM from filesystem
Generating / converting
- Import from
crypto.*—jwk.Import[T]wrapping RSA/EC/OKP keys - Key-specific methods — typed accessors on
RSAPublicKey,ECDSAPrivateKey, etc. - Struct field tagging — embed
jwk.Keyin your own types
Extending (custom key types / formats)
- Custom x509/PEM encoder & decoder — register your own PEM block type via
jwk/jwkbb, the building-block API used by extension modules
Fetching
Fetch— one-shot HTTP retrieval via thejwkfetchcompanionCache— background-refreshed JWK Set store- Cached set as a JWKS — pass a cache to
jwt.WithKeySet - URL whitelist — restrict which URLs
jwkfetchwill dereference (required forjku)
Comparing / filtering
- Key comparison — structural and identity-based comparisons
- Basic filter
- Advanced filter
Extension modules
Each extension is a separate module under github.com/jwx-go/*. Import for side effects.
Post-quantum signatures (ML-DSA)
- Sign / verify — ML-DSA-44/65/87 via
github.com/jwx-go/mldsa/v4 - JWK round-trip — AKP key type,
"alg"field requirement - Export to raw key
Post-quantum key encapsulation (ML-KEM)
- Encrypt / decrypt — ML-KEM-768/1024 via
github.com/jwx-go/mlkem/v4
Hybrid PQ HPKE
- Encrypt / decrypt — via
github.com/jwx-go/reddy-pqchpke/v4(experimental)
Composite signatures
- Sign / verify — ML-DSA + classical via
github.com/jwx-go/compsig/v4(experimental)
Niche curves
- ES256K (secp256k1) — see JWS Sign section
- Ed448 — see JWS Sign section
Tooling / backends
- ASM-optimized base64 — high-throughput base64 backend via
github.com/jwx-go/asmbase64/v4
Library-wide
- Cross-package overview
- README example — the snippet that appears in the main jwx README
- Register custom EC curve and key type
Contributing a new example
- One example per file. File name:
<topic>_<action>_example_test.go. - Function name:
Example_<topic>_<action>()— the matching slug without_example_test.go. - Add a line to the topical index above in the same PR.
- Include ample inline comments that explain why the code is shaped the way it is.
- End with an
// OUTPUT:block — even an empty one if the function prints nothing.
See CLAUDE.md for the full conventions.