JWT: A Short Explanation
- 5 minutes readIntroduction
This article aims to be a short explanation of the three parts (header, payload, signature) of a JSON Web Token, how they are generated and validated.
Anatomy Overview
A JWT consists of three parts, each delimited by a “.” (dot) like the following:header.payload.signature
Basic overview of the three parts
Header
The header of a JWT usually contains the signing algorithm that was used, the type of the token, in this case “JWT” and optionally, if signed, a “Key ID” (kid).
Base64url-decoding the JWT header produces the following:
{
"typ": "JWT",
"alg": "HS256"
}
Payload
The payload of a JWT contains a set of claims being made. Different types of claims:
- Registered claims: standardised and recommended, like ‘iss’, ‘sub’, ’exp’.
- Public claims: non-registered claims that should be collision-resistant, like ‘preferred_username’, ‘roles’, ’email’.
- Some are defined in the IANA “JSON Web Token Claims” registry.
- Private claims: non-registered claims without care for collisions.
Base64url-decoding the JWT payload produces the following:
{
"iss": "joe",
"exp": 1300819380,
"http://example.com/is_root": true
}
Signature
The signature of a JWT ensures the token hasn’t been tampered with, and, if signed, can be used to verify the identity of the JWT’s sender.
Example base64url-encoded signature:
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Everything put together
Payload, Header and signature base64url-encoded:
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Generating the token
Header & Payload
The header and payload are each encoded using base64url encoding and then joined together with a “.” (dot) (JWS Signing Input).
(header)
{
"typ": "JWT",
"alg": "HS256"
}
+ (payload)
{
"iss": "joe",
"exp": 1300819380,
"http://example.com/is_root": true
}
becomes
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
Signature creation
The signature is generated using the following (simplified) process:
- Join the base64url-encoded header and base64url-encoded payload with a “.” (dot) (JWS Signing Input).
- Compute the MAC of the previous value by applying the specified algorithm (ex: HS256, RS256) with the secret or private key.
- Base64url-encode the resulting signature from the previous step.
Examples:
- ex: base64url(HS256(base64url(header) + “.” + base64url(payload), secret_key))
- ex: base64url(RS256(base64url(header) + “.” + base64url(payload), private_key))
Verifying the token
The JWT is verified using the following (simplified) process:
- Extract all three parts of the JWT.
- Base64url-decode the header and retrieve the “alg” to use.
- Join the base64url-encoded header and base64url-encoded payload with a “.” (dot) (JWS Signing Input).
- Use the validation method defined for the algorithm being used.
- HS256 (symmetric):
- The signature is reproduced by hashing the JWS Signing Input with the shared secret key.
- The reproduced signature is then compared to the signature in the JWT.
- RS256 (asymmetric):
- The JWT’s signature is decrypted using the public key, exposing a SHA256 hash.
- A new SHA256 hash is computed from the JWS Signing Input of the JWT.
- If both hashes match, the token is validated.
- HS256 (symmetric):
Conclusion
I hope this article provided a clear and helpful introduction to the basic principles of JSON Web Tokens. For a deeper understanding and to verify the information yourself, I recommend you to experiment with JWT and read the relevant RFC standards.
Quick references
Links
- RFC 4648 (base64url encoding)
- RFC 7515 / JSON Web Signature (JWS)
- RFC 7519 / JSON Web Token (JWT)
- Introduction to JWT
- JWT Debugger