We've discussed how scopes limit what a token can do, but how is the token actually constructed? While OAuth allows any token format, JSON Web Tokens (JWT) have become the industry standard because they are self-contained.
A JWT is composed of three Base64URL-encoded parts separated by dots. Because the payload is only encoded (not encrypted), anyone with the token can read the data inside.
Crucial: Base64 is NOT encryption. Never put sensitive secrets like passwords or raw API keys inside a JWT payload.
// Part 1: Header
{ "alg": "HS256", "typ": "JWT" }
// Part 2: Payload (Claims)
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622,
"scope": "read:profile"
}
// Part 3: Signature
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)The signature is the most important part. It allows the Resource Server to verify that the token was actually issued by the Authorization Server and has not been tampered with.
๐ก HS256 (Symmetric) uses a shared secret. RS256 (Asymmetric) uses a Private Key to sign and a Public Key to verify.
| Algorithm | Key Type | Security | Best For |
|---|---|---|---|
| HS256 | Shared Secret | Medium | Internal services with shared secrets |
| RS256 | Public/Private Pair | High | Public APIs, External Third Parties |
| ES256 | Elliptic Curve | Very High | Mobile apps, high-performance needs |
When a Resource Server receives a JWT, it must perform these checks in order: 1. Verify the signature, 2. Check the expiration (`exp`), 3. Verify the issuer (`iss`), and 4. Validate the audience (`aud`).
The 'None' Algorithm Attack: Some libraries allow a JWT with `alg: none`. Attackers can change the header to `none`, remove the signature, and modify the payload to gain admin access.
Verify exercises to earn โ 220 XP and unlock next lab level.