backend / authentication / jwt / 08_jose_family.md

The JOSE Family — JWS, JWE, JWK, JWA, JWT

7 interview angles 8 min read source

The JOSE Family — JWS, JWE, JWK, JWA, JWT

JWT is the famous one. It rides on top of a family of related specs collectively called JOSE (JavaScript Object Signing and Encryption). When people say “JWT” they almost always mean “signed JWT” = a JWS with JWT-shaped claims.

The user may have asked about “JWI” — that’s not a standard JOSE acronym. The most likely meanings: JWE (encryption, JWT’s encrypted counterpart), or possibly JWS (signature) or JWK (key). This file covers all of them briefly.

The family tree

                   JOSE
   (JavaScript Object Signing and Encryption)

        ┌────────────┼────────────┬──────────┐
        ↓            ↓            ↓          ↓
       JWS          JWE          JWK        JWA
   (Signature)  (Encryption)    (Key)   (Algorithms)
        │            │
        └─────┬──────┘

             JWT
       (JSON Web Token)
Spec RFC What
JWS 7515 JSON Web Signature — sign a payload, verify the signature
JWE 7516 JSON Web Encryption — encrypt a payload, decrypt with a key
JWK 7517 JSON Web Key — represent a cryptographic key as JSON
JWA 7518 JSON Web Algorithms — names of algorithms (RS256, A256GCM, etc.)
JWT 7519 JSON Web Token — a payload of claims, wrapped in JWS (or JWE)

JWT is the application; JWS/JWE provides the wire format; JWK is for key distribution; JWA is the vocabulary.

JWS — JSON Web Signature (the common case)

header.payload.signature

This is what 99% of “JWTs” actually are: a JWS with a JSON payload of claims.

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyXzQyIiwiZXhwIjoxNzE2MzIwMDAwfQ.SflKxw...
└── header ──┘└────── payload (visible) ──────┘└── signature ──┘
  • Header declares the signing algorithm.
  • Payload is whatever JSON (for JWT: claims; for plain JWS: anything).
  • Signature proves the payload wasn’t tampered.

The payload is not encrypted. Anyone with the token reads the claims. Signature ≠ confidentiality.

JWE — JSON Web Encryption (the encrypted alternative)

Five base64url segments (not three):

header.encryptedKey.iv.ciphertext.tag
Segment Means
header algorithms used (alg for key encryption, enc for content encryption)
encryptedKey the symmetric content-encryption key, encrypted with the recipient’s public key
iv initialization vector for the content encryption
ciphertext the actual encrypted payload
tag authentication tag (AEAD)
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.abc...def.ghi...jkl.mno...pqr.stu...vwx

The payload is encrypted, not just signed. Anyone without the recipient’s private key cannot read the contents — they see only ciphertext.

When to use JWE

  • Tokens that contain PII or sensitive data.
  • Multi-hop scenarios where intermediaries shouldn’t read the contents.
  • Compliance / regulatory requirements (HIPAA, PCI in some cases).

When NOT to use JWE

  • Most apps don’t need it. TLS already encrypts in transit; JWE adds protection at rest / in logs / at intermediaries.
  • For confidentiality of session data, server-side sessions with an opaque ID are simpler.
  • JWE adds significant complexity (more algorithms, key distribution, payload size).

JWE algorithm examples

Header alg Means Use case
RSA-OAEP-256 RSA-OAEP key wrap recipient has RSA keypair
ECDH-ES+A256KW ECDH key agreement + AES key wrap recipient has EC keypair
dir direct (the key in JWK is the content encryption key) symmetric scenarios
A256KW AES key wrap symmetric scenarios

Header enc (content encryption):

enc Means
A256GCM AES-256-GCM (recommended)
A128CBC-HS256 AES-128-CBC + HMAC-SHA-256

For most uses: RSA-OAEP-256 + A256GCM.

Python JWE (with python-jose)

# PyJWT does NOT support JWE.
# Use python-jose or jwcrypto:
from jose import jwe

ciphertext = jwe.encrypt(
    plaintext=b'{"sub": "user_42"}',
    key=recipient_public_key,
    algorithm="RSA-OAEP-256",
    encryption="A256GCM",
)

plaintext = jwe.decrypt(ciphertext, recipient_private_key)

JWE is rare. Most teams never touch it.

JWK — JSON Web Key

A JSON representation of a cryptographic key.

{
  "kty": "RSA",
  "kid": "key-2024-q1",
  "use": "sig",
  "alg": "RS256",
  "n": "0vx7agoebGcQSuuPiL...",
  "e": "AQAB"
}

Fields:

Field Means
kty key type (RSA, EC, oct for symmetric, OKP for Ed25519)
kid key ID (for rotation / lookup)
use sig (signing) or enc (encryption)
alg algorithm the key is intended for
n, e RSA modulus and exponent
crv, x, y EC curve and coordinates
k symmetric key (base64url)

For RSA: n and e are the public key. Private key adds d (private exponent) and others.

JWKS — JSON Web Key Set

A set of JWKs. Most OIDC providers publish their public keys at:

GET https://auth.example.com/.well-known/jwks.json

Returns:

{
  "keys": [
    {"kty": "RSA", "kid": "key1", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB"},
    {"kty": "RSA", "kid": "key2", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB"}
  ]
}

Verifiers fetch this once (or on rotation), cache it, and look up the matching key by kid.

JWKS makes key rotation transparent: issuer adds a new kid, updates JWKS; verifiers fetch the new list; old kid still works until removed.

JWA — JSON Web Algorithms

Defines the names. When you see alg: RS256 in a JWT header, the meaning of “RS256” is defined in JWA: “RSASSA-PKCS1-v1_5 using SHA-256.”

Selected JWA algorithm names:

Name Means
HS256/384/512 HMAC with SHA-256/384/512
RS256/384/512 RSA-PKCS1-v1_5 with SHA-256/384/512
ES256/384/512 ECDSA with P-256/384/521 + SHA-256/384/512
PS256/384/512 RSA-PSS with SHA-256/384/512
EdDSA Ed25519 / Ed448
none no signature (NEVER use)
A128KW/A256KW AES key wrap
RSA-OAEP/RSA-OAEP-256 RSA-OAEP
A128GCM/A256GCM AES-GCM (for JWE content)
dir direct key (JWE)

The library handles the actual cryptography; JWA just standardizes the names.

Compact vs JSON serialization

JWS and JWE have two serialization formats:

Compact JSON
Format a.b.c (or a.b.c.d.e for JWE) full JSON object
Size small large
Multiple signatures no yes
Use URL-friendly, headers, cookies server-to-server, multi-signer scenarios

JWT uses compact. JSON serialization is rare and mostly for advanced multi-recipient scenarios.

When you’ll meet each in real life

Spec Real-world frequency
JWT (JWS-based) very common — OIDC, API auth, SSO
JWS (non-JWT) rare — used for signing arbitrary JSON
JWE rare — when JWT contents must be confidential
JWK common — for OIDC verifier setup
JWA implicit — every JWT references JWA names

99% of JOSE work is JWT + JWK (for verification). JWE shows up in regulated industries.

“JWI” — what it might mean

If the interviewer said “JWI”:

Possibility Real name
JWE typo JSON Web Encryption (the encrypted JWT counterpart)
jti claim JWT ID (per-token unique identifier; see 03_claims.md)
JWS confusion JSON Web Signature (the signed JWT counterpart)
Made-up not a standard JOSE acronym

The most defensible answer: “If ‘JWI’ means JWE — that’s encrypted JWT, used when the payload must be confidential. Most JWTs are JWS (signed only). If ‘JWI’ is the jti claim — that’s the JWT ID for replay prevention / revocation. Otherwise, the standard JOSE family is JWS, JWE, JWK, JWA, JWT.”

Common pitfalls

  • Confusing JWS and JWT — every JWT is structurally a JWS (or rarely a JWE) but not every JWS is a JWT. JWT specifies a JSON payload of claims; JWS is the generic signature container.
  • Assuming JWT is encrypted — it’s signed only. Use JWE for encryption.
  • Hardcoding the algorithm name — JWA defines the standard names; mistype RS256 as RSA256 and your library rejects it.
  • Loading JWKs without kid — when keys rotate, you can’t tell which key signed an old token.

Common interview confusions

  • “JWE is just an encrypted JWT.” — yes, but the use cases are rare. Most JWTs you’ll see are signed (JWS), not encrypted (JWE). For confidentiality, server-side sessions are usually simpler.
  • “JWK is for symmetric keys only.” — JWK represents any key type: RSA (kty: RSA), EC (kty: EC), symmetric (kty: oct), Ed25519 (kty: OKP).
  • “JOSE means JSON.” — JOSE is the umbrella spec family. JSON is just the format JOSE uses.

Interview angle

  • “What’s the JOSE family?” — JavaScript Object Signing and Encryption. Five specs: JWS (signature), JWE (encryption), JWK (key representation), JWA (algorithm names), JWT (claims payload). Most “JWTs” are JWS-wrapped JSON claims.
  • “JWT vs JWS vs JWE?” — JWS = a signed payload, generic. JWE = an encrypted payload, generic. JWT = a specific kind of payload (JSON claims), wrapped in JWS (signed) or rarely JWE (encrypted).
  • “What’s a JWK?” — JSON representation of a cryptographic key. Includes kty (key type), kid (key ID for rotation), use (sig/enc), and key material. JWKS = a set of them, typically published by OIDC providers at .well-known/jwks.json.
  • “When would you use JWE?” — when the token’s contents must be confidential (PII, sensitive data) AND TLS isn’t enough (multi-hop, logs, intermediaries). Rare; most apps use signed JWT + opaque session IDs for confidentiality.
  • “How do JWS, JWE, JWT relate?” — JWT is the application (claims payload). JWS is the wire format for signed JWTs (the common case). JWE is the wire format for encrypted JWTs (rare). All three are part of the JOSE family.
  • “What’s kid for in JWKS?” — key ID. The JWT header includes kid; the verifier looks up the matching key in the JWKS by that ID. Enables key rotation: add new keys to JWKS, old kids keep working until removed.
  • “If asked about ‘JWI’…” — clarify which member of the JOSE family they mean. Most likely JWE (encrypted JWT), occasionally jti (JWT ID claim), or just a typo. Standard JOSE specs are JWS / JWE / JWK / JWA / JWT.