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.

"JWT" specifically refers to tokens whose payload is a JSON object of claims (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.

JWS or JWE? Signed is the default choice. Encrypt only when you have a concrete reason — encrypted tokens can't be inspected in logs, shown in DevTools, or debugged by the frontend team. You can also nest a JWS inside a JWE if you want to make sure the sender is trusted and the payload is confidential, but that's a more complex workflow.

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:

ClaimMeaningValidated by verify() / decrypt()
issIssuerOnly if options.issuer is set
subSubjectOnly if options.subject is set
audAudienceOnly if options.audience is set
expExpires at (seconds)Always — rejects expired tokens
nbfNot before (seconds)Always — rejects tokens used before the specified time
iatIssued at (seconds)Type-checked; used with options.maxTokenAge
jtiJWT IDNot validated, but the H3 session adapters use it as a session.id
typType 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 (alg in a JWS): HMAC (HS*), RSA (RS*, PS*), ECDSA (ES*), EdDSA (Ed25519). See JWS algorithms.
  • Key-management algorithms (alg in 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 (enc in 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?