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.

The compact form is the most common, but both specs define richer JSON Serializations too — General (multi-signer / multi-recipient) and Flattened (single-signer / single-recipient, but in JSON shape). unjwt supports these through 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 youNested JWT (JWS-in-JWE)

JWS is the default. Encrypt only when the content itself needs to be hidden.

A nested JWT — signing a payload, then encrypting the resulting JWS — gives you both authenticity and confidentiality. Do it by encrypting a signed token: pass the JWS string as the payload to 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):

For JWE (encrypted tokens):

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 an exp claim relative to iat. Accepts 30 /* seconds */, "30s", "10m", "2h", "7D", "1W", "3M", "1Y" and the long-form "7days" / "3months" / "1year" (no space between number and unit).
  • currentDate — override "now" for iat/exp calculation (useful in tests).
  • protectedHeader — extra header parameters (kid, typ, cty, custom fields). alg/enc are managed by the library and can't be overridden here.

Claim validation is shared too — see JWTClaimValidationOptions.

Next

  • JWS → — signing and verifying.
  • JWE → — encrypting and decrypting.