JWT and JOSE are the “serialization + crypto” toolbox behind a lot of modern IAM.
- JWT is a token format (three base64url parts).
- JOSE is the family of specs around signing/encryption and key distribution.
JWTs are also one of the most commonly mis-validated artifacts in production.
What the acronyms mean
- JWT: JSON Web Token (the compact
header.payload.signatureformat) - JWS: JSON Web Signature (signing)
- JWE: JSON Web Encryption (encryption)
- JWK: JSON Web Key (a public key description)
- JWKS: a set of JWKs (published by an issuer)
Diagram: who signs and who validates
Diagram
JWT structure (what’s inside)
A compact JWT has:
- Header (metadata)
- Payload (claims)
- Signature (or MAC)
Example header:
json
{
"alg": "RS256",
"kid": "abc123",
"typ": "JWT"
}Example payload:
json
{
"iss": "https://issuer.example.com",
"sub": "00u123",
"aud": "api://payments",
"exp": 1760000000,
"iat": 1759996400,
"scp": ["payments:read"]
}The non-negotiable validation checklist
When validating a JWT, at minimum:
- Verify the signature using the correct key
- Verify
algis expected (never acceptnone) - Verify
issis what you expect - Verify
audcontains your audience - Verify
expis not expired (clock skew allowance) - If present/required, verify
nbf,nonce,azp
Common catastrophic mistake
- “Decode only” validation (base64 decode and trust claims).
JWK / JWKS: key rotation in real life
Why kid exists:
- issuers rotate keys
- the verifier chooses the correct key via
kid
Operational best practices:
- cache JWKS for a short TTL
- support multiple keys simultaneously (overlap during rotation)
- handle “kid not found” by refreshing JWKS once
JWS vs JWE: sign vs encrypt
- Use JWS when you need integrity/authenticity and the payload can be visible.
- Use JWE when the payload itself must be confidential.
In many IAM systems:
- ID tokens are JWS
- access tokens are often JWS (or opaque)
- JWE is less common, but can be used for sensitive claims
Troubleshooting patterns
- Signature invalid after key rotation → stale JWKS cache
- Token valid in one service, invalid in another → audience mismatch
- Random failures around exp/nbf → clock skew
