An Introduction To JSON Web Tokens
Networking
01/04/2021
A JSON Web Token, or JWT for short, is an authorization web standard for client-to-server or even server-to-server communication. Authorization should not be confused with authentication, where:
- Authorization: Checks whether a user has the permission to access a certain resource,
- Authentication: Checks whether a user really is who they claim to be.
How it works
To understand how exactly it's used, let's imagine the following scenario on a website.
Image from Stack Overflow
Step 1
The user starts off logging in to the website by sending a POST request to the backend.
Step 2
Upon receiving the user credentials from the client, the server authenticates the user. If successful, it then generates a JWT using a secret key. The token includes some kind of user information such as a user id, so that the server can easily identify the client in future requests.
Step 3
The server sends a response to the client that includes the newly created JWT, with the token then stored in the browser.
Step 4
The client sends a new request, let's say, to access a page. The JWT is included in the request header in the Authorization
field. Notice that the JWT is prepended by the keyword Bearer.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI...2QT4fwpMeJf36POk6yJV_adQsw5c
Step 5
The server verifies the authenticity of the JWT with its secret key, making sure it has not been tampered with. If successful, any user information included in the token is used to identify the user's permissions.
Step 6
A response is sent back to the client, either containing the requested page or an error depending on the user's permissions.
The structure
Let's dive a level deeper. A JWT will typically have the following layout: xxxxx.yyyyy.zzzzz
. The dots serve the purpose of separating 3 things:
- The header (x),
- Payload (y), and
- Signature (z)
Header
The header consists of a JSON Object which typically holds two types of data:
- The signing algorithm (in this case HS256), and
- The token type (in this case JWT... of course! 😆)
{ "alg": "HS256", "typ": "JWT"}
This JSON Object is then Base64url encoded and placed in the 1st spot of the token layout.
Payload
The payload is yet another JSON object with more information. The important thing to notice here is that there are predefined property names: either as reserved names called registered claims, or through agreement, called public claims. A comprehensive list can be viewed on the IANA website, with the former names registered by IESG, and the latter by OpenID Foundation. Examples are iss
(issuer), exp
(expiration) and name
(full name).
You may of course name custom properties if you wish to do so.
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022}
Once again, the JSON Object is Base64url encoded and placed in the 2nd spot of the token layout.
Be aware that anyone who has access to your JWT can decode and read this information. If you decide to use sensitive data, make sure to encrypt it first.
Signature
The purpose of the signature is to be certain that none of the above-mentioned information has been changed. To obtain the signature, you simply add the encoded header and payload, and then encode (aka sign) it with your secret key using the specified algorithm.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT debugger
Jwt.io offers a great debugger with which you can play around and see how the encoded values and their validity change depending on different inputs. Give it a try! 🚀