JWT
A JSON Web Token (RFC 7519) is a short string that carries a JSON payload across systems — typically for authentication, authorization, or short-lived messages. Every JWT is either:
- a JSON Web Signature (JWS) — the payload is readable, but tampering is detectable, or
- a JSON Web Encryption (JWE) — the payload is unreadable without the right key.
Both share the same outer shape: three to five base64url-encoded segments joined by dots. What differs is what happens between sign() / verify() (JWS) and encrypt() / decrypt() (JWE).
Anatomy
A typical compact JWS has three parts:
eyJhbGci... .eyJzdWIi... .MEUCIQDwW0...
<header> .<payload> .<signature>
- Header — algorithm (
alg), type (typ), key id (kid), etc. - Payload — the JSON claims, base64url-encoded.
- Signature — a MAC or digital signature over
header.payload.
A compact JWE has five parts:
eyJhbGci... .e1h3WklRxw... .48V1_ALb6... .5eym8TW_c... .XFBoMYUZo...
<header> .<encryptedKey> .<iv> .<ciphertext> .<tag>
The payload is gone — replaced by ciphertext that only the recipient's key can unlock, plus an IV and an authentication tag. The encryptedKey segment is the Content Encryption Key, itself wrapped by the recipient's key.
signMulti/verifyMulti and encryptMulti/decryptMulti.When to sign vs. encrypt
| If the data is… | Use… |
|---|---|
| Non-sensitive identity data (user id, role) | JWS |
| Inspectable by the client (preferences, flags) | JWS |
| Readable by third parties (federated identity) | JWS |
| Sensitive (tokens, PII, secrets, refresh state) | JWE |
| Both confidential and provably from you | Nested JWT (JWS-in-JWE) |
JWS is the default. Encrypt only when the content itself needs to be hidden.
encrypt() with typ: "JWT"/cty: "JWT" headers. unjwt doesn't add syntax sugar for this because it's already one line.What unjwt gives you
For JWS (signed tokens):
sign()/verify()— compact serialization, the common case.signMulti()/verifyMulti()/verifyMultiAll()— General JSON Serialization with multiple signers.
For JWE (encrypted tokens):
encrypt()/decrypt()— compact serialization.encryptMulti()/decryptMulti()— General JSON Serialization with multiple recipients.- ECDH-ES and password-based flows as first-class paths.
Both pages below give you the overview and basic usage; sub-pages go into each function in detail.
Common options, both sides
A few options show up identically on both signing and encryption:
expiresIn— adds anexpclaim relative toiat. Accepts30 /* seconds */,"30s","10m","2h","7D","1W","3M","1Y"and the long-form"7days"/"3months"/"1year"(no space between number and unit).currentDate— override "now" foriat/expcalculation (useful in tests).protectedHeader— extra header parameters (kid,typ,cty, custom fields).alg/encare managed by the library and can't be overridden here.
Claim validation is shared too — see JWTClaimValidationOptions.