JSON Web Token or JWT (pronounced “jot”) is a standard for passing data (called claims) in a JSON object format. Two of its key features are its compactness and simplicity. A JWT can be signed or encrypted to provide security and to verify its authenticity.
JWT Structure
A typical JWT consists of three parts: header, payload, signature. It could look like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOjEyMzQ1LCJuYW1lIjoiRW1tYW51ZWwgQWxsaXNvbiIsInJvbGUiOiJBZG1pbiIsImlhdCI6MTY0MTAzODQ0Nn0.
07D273ZIEToghySEQnch94zB98UHVy1bVZv3d1mVsEw
Now, don’t fret 😂. Looks like gibberish, right? That is a JWT in its compact form. It contains the header, payload and signature, all encoded in URL-safe Base64 format (also called Base64Url). Notice that a dot (”.”) is used to separate the 3 parts of the JWT. In its JSON format, it would look like this:
The header:
{
"alg": "HS256",
"typ": "JWT"
}
The payload:
{
"sub": 12345,
"name": "Emmanuel Allison",
"role": "Admin"
}
Let's discuss the different parts, shall we?
The header
The header usually contains information about the JWT itself. Here, we know if the token is signed or not, encrypted or not. In our example, the header contains two claims:
- alg: which is used to signify the algorithm used to sign the JWT. Set to “none” if the JWT isn’t signed. This is the only claim that is required in a JWT’s header.
- typ: the media type. JWT in this case.
The payload
Here’s where the other data can be passed. Three types of claims can be added here:
- Registered claims: These are claims specified in the JWT spec. There are not compulsory, but can be helpful when used. Examples of them include: iss (issuer), aud (audience), sub (subject), exp (expiration date in the format “seconds since epoch”), iat (issued at time).
- Public claims: These are claims that have been defined and registered in the IANA JSON Web Tokens registry or contain a namespace to prevent collisions.
- Private claims: These claims are defined by the users of the JWT to pass information. These claims’ names should not collide with registered or public claims. In our example, we have three claims that are from two of the categories discussed above. We have sub, the subject claim (in this case is the ID of the user) which is a registered claim. And then, we have two private claims: name and role.
🚫 Do not put sensitive data in the header and payload except they are encrypted, because they can be read.
The signature
When a JWT is signed, it can be verified for authenticity. This shields the parties (to a good degree) from attacks where the JWT is modified. There are several algorithms used to sign a JWT and some are HS256, RS256 and ES256. Here's how a signature is made:
// The header and payload are encoded into Base64Url, concatenated with a
// dot and sent alongside a secret key into the chosen algorithm.
HS256((base64Url(header) + "." + base64Url(payload)), secret)
Use Cases
Alright, we’ve come so far in understanding how a JWT looks and is made, but where can we apply this? JWTs can be used for authentication, authorization. They can also be used for client-side or stateless sessions.
To learn more, visit jwt.io, and for fun, put in “Shhh! This is a secret.” as the secret, copy and paste the compact JWT in this article into their debugger, and watch for what it says 🙂.