Json Web Tokens
by allencharp
What is JWT
JSON Web Token (JWT, RFC 7519) is a compact, URL-safe token format used to transmit claims between parties. First, take a look at this JWT debugger.
Simply put, a JWT is a string with the following format:
header.payload.signature
Each part is base64url encoded (base64 with - and _ instead of + and /, and no padding =), so the token can safely appear in URLs and HTTP headers.
Header
{
"typ": "JWT",
"alg": "HS256"
}
typ is of course JWT, and the signing algorithm here is HS256 (HMAC-SHA256). The header tells the verifier how the token was signed — which is exactly why the algorithm must be trusted explicitly (see attacks below).
Payload
The payload component is the data stored in the JWT. There are some optional registered claims, such as:
iss— issuersub— subjectexp— expiration timeiat— issued at
{
"userId": "1101001",
"name": "Allen",
"exp": 1547078400
}
Note:
expis a NumericDate (Unix timestamp), not a date string. An expired token must be rejected.
Signature
The JWT signature is computed roughly like this:
data = base64urlEncode( header ) + '.' + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )
The signature proves that the token was created by someone who knows the secret (HS256) or owns the private key (RS256).
How does JWT protect data
Most importantly, JWT is not a way to encrypt the data — it is a way to prove the data was created by an authentic source, so the data can be easily decoded and read.
JWT does not guarantee any security for sensitive data. Do not save sensitive data in a JWT.
Common JWT Attacks
1. alg: none
Some libraries accept a token whose header says "alg": "none" and skip signature verification entirely. An attacker can forge a token with arbitrary claims:
{"alg": "none", "typ": "JWT"}
Fix: always verify the signature; reject none and enforce an explicit algorithm allowlist.
2. Algorithm confusion (RS256 → HS256)
The server verifies RS256 tokens with the public key, but HS256 tokens with a shared secret. If the server blindly trusts the alg header, an attacker can send an HS256 token signed with the server’s public key — the server treats the public key as the HMAC secret and accepts the forgery.
Fix: pin the expected algorithm server-side; never derive it from the token header.
3. Weak secret brute force
For HS256, the HMAC secret is shared. If it is weak (a common word), offline brute force with a wordlist is trivial once a valid token is obtained.
Fix: use a high-entropy random secret, rotate it regularly.
Secure Usage Checklist
- Always verify the signature — there is no exception for
none. - Validate
exp,nbfandiss/audclaims. - Whitelist the allowed algorithms (e.g. only RS256) and pin them.
- Never store sensitive data in the payload (it is only base64, not encrypted).
- Prefer short-lived access tokens combined with refresh tokens.
Summary
JWT is a signing mechanism, not encryption. The security of a JWT-based system depends on strict signature verification, an explicit algorithm allowlist, and keeping secrets high-entropy. Most real-world JWT vulnerabilities come from implementations that trust attacker-controlled alg values.