Everyone tells you JWTs have three parts separated by dots, but let's actually understand what each part does in practice. I've worked with hundreds of authentication systems, and the difference between knowing the structure and actually understanding it saves hours of debugging.
The Header - Not Just Algorithm Info
The header does more than specify HS256 or RS256. When you see "typ": "JWT", that's telling parsers this is definitely a JWT and not some other token format. The "alg" field is crucial—it determines how the signature was created. But here's what most tutorials miss: if someone changes this algorithm claim, your verification logic better check it matches what you expect, or you could have security issues.
The Payload - Where Your Actual Data Lives
This is the interesting part. There are reserved claims that have special meaning: sub (subject, usually user ID), exp (expiration timestamp), iat (issued at). Then there are custom claims—anything you want to add. I've seen teams put user roles, permissions, even UI preferences here. But remember: this data is readable by anyone who gets the token, so don't put sensitive information here.
The Signature - The Actual Security Part
This tool doesn't touch the signature, but you should know what it does. The signature takes the header and payload, adds a secret key, and creates a cryptographic hash. If anyone changes even one character in the header or payload, the signature won't match. That's how your application knows the token hasn't been tampered with. Without proper signature verification, JWTs are just fancy JSON containers.
Pro tip: Notice how the token uses dots as separators? That's intentional—it makes JWTs easy to split in code. The Base64Url encoding (with - and _ instead of + and /) means you can safely put JWTs in URLs without encoding issues. These small design choices make JWTs work smoothly across web browsers, mobile apps, and API gateways.