Core concepts
The JOSE specs (short for JavaScript Object Signing and Encryption) use several acronyms that sound alike. This page is the shortest explanation of each that still makes sense.
JWT — JSON Web Token
A JWT is the end product: a small string that carries some JSON data, and is either signed or encrypted so the receiver can trust it.
eyJhbGciOi...eyJzdWIiOi...SflKxwRJSM...
<header> .<payload> .<signature>
Three base64url segments joined by dots. That's the "Compact Serialization" — by far the most common form.
Defined in RFC 7519.
sub, exp, iss, …). The broader term for the same dotted format is JOSE token, and its payload can be any bytes. unjwt handles both — if you pass a string or Uint8Array to sign()/encrypt(), you get a valid JOSE token that isn't technically a JWT.JWS — JSON Web Signature
A JWS is a JWT whose payload is signed. Anyone can read the payload; only the holder of the signing key could have produced the signature.
Use when:
- You want the client to read the data (user ID, role, expiration) but trust it came from you.
- The data is non-sensitive.
Defined in RFC 7515. → JWS in unjwt.
JWE — JSON Web Encryption
A JWE is a JWT whose payload is encrypted. Only the holder of the decryption key can read the data. Anyone else sees opaque ciphertext.
Use when:
- The payload contains sensitive data the client (or intermediary) should not see.
- You want to keep the self-contained, signed-like shape of a JWT but with confidentiality.
Defined in RFC 7516. → JWE in unjwt.
JWK — JSON Web Key
A JWK is a way to represent a cryptographic key as a JSON object. Every signing, verifying, encrypting, and decrypting operation involves a key; a JWK is unjwt's preferred way to pass keys around.
{
"kty": "oct",
"k": "GawgguFyGrWKav7AX4VKUg",
"alg": "HS256",
"kid": "4c3d..."
}
A JWK Set (or JWKS) is simply a JSON document with a keys array — typically published at /.well-known/jwks.json by OAuth/OIDC providers.
Defined in RFC 7517. → JWK in unjwt.
How they fit together
┌─────────────────────────────┐
│ JWT │ ← the portable string
└──────────────┬──────────────┘
│
┌────────────┴────────────┐
▼ ▼
JWS JWE
(signed) (encrypted)
│ │
└────────────┬────────────┘
▼
JWK
(the key used to produce or consume the above)
- A JWT is either a JWS or a JWE.
- Both use a JWK as the key (or a
CryptoKey/ password / raw bytes, which unjwt normalizes internally).
The claims you'll actually see
Inside a JWT payload, certain claim names are standardized. unjwt validates the ones that affect security automatically:
| Claim | Meaning | Validated by verify() / decrypt() |
|---|---|---|
iss | Issuer | Only if options.issuer is set |
sub | Subject | Only if options.subject is set |
aud | Audience | Only if options.audience is set |
exp | Expires at (seconds) | Always — rejects expired tokens |
nbf | Not before (seconds) | Always — rejects tokens used before the specified time |
iat | Issued at (seconds) | Type-checked; used with options.maxTokenAge |
jti | JWT ID | Not validated, but the H3 session adapters use it as a session.id |
typ | Type header (e.g. JWT) | Only if options.typ is set |
Full definitions in RFC 7519 §4.1.
What's an "algorithm"?
A JWS or JWE header always carries an alg field naming the algorithm the token was produced with. unjwt reads it back to choose the preferred verification path. The algorithms split into two families:
- Signing algorithms (
algin a JWS): HMAC (HS*), RSA (RS*,PS*), ECDSA (ES*), EdDSA (Ed25519). See JWS algorithms. - Key-management algorithms (
algin a JWE): how the content key is delivered. Direct (dir), AES Key Wrap, RSA-OAEP, PBES2, ECDH-ES. See JWE algorithms.
Plus one more for JWE only:
- Content-encryption algorithms (
encin a JWE): AES-GCM or AES-CBC+HMAC-SHA2 — the cipher that encrypts the actual payload.
When you pass a JWK that has an alg field set (which generateJWK() always does), unjwt uses it automatically. You only need to specify alg/enc explicitly when the key carries no such metadata (raw bytes, untyped JWKs, CryptoKey objects without algorithm hints).
Full algorithm registry: RFC 7518.
Ready?
- If you want to start writing code: Quickstart →
- If you want to understand the signed path: JWS →
- If you want the encrypted path: JWE →