JWT
Why do we need the JSON Web Token (JWT) in the modern web?
The Problem
The HTTP protocol is stateless, it means each request has no idea about the previous request, so we need to reauthenticate for each request.
The traditional way of solving the problem is to use server side sessions. Once the server checks username and password it will create a session id and save it in memory, the client will then use session id to communicate.
The solution isn’t scale, as the server needs to maintain a huge amount of sessions and multiple servers need to share all the session information.
How JWT solves the problem
JWT Content
JWT is self-contained, meaning all the information required by the server to approve or reject a request to an API.
A JWT has header, payload and signature.
The header section contains information about the token itself.
{
"kid": "ywdoAL4WL...rV4InvRo=",
"alg": "RS256"
}
The payload section contains information about the client (claims etc.).
{
[...]
"iss": "https://cognito-idp.eu-west-1.amazonaws.com/XXX",
"name": "Mariano Calandra",
"admin": false
}
The third section is signature, it is a hash that computed by the following step: * Join with a dot the encoded header and the encoded payload; * Hash the result using “alg” (RS256) and a private key; * Encode the result as Base64URL;
data = base64UrlEncode(header) + "." + base64UrlEncode(payload);
hash = RS256(data, private_key);
signature = base64UrlEncode(hash);
JWT Validation
Since JWT is self-contained, we have all the information needed to validate the token. We now need to know how to get the public key to perform the validation.
Note that in asymmetric encryption, the public key is used to encrypt a message, private key is used to decrypt it. In the signing algorithm it is opposite. In a JWT data is signed using a private key and the public key is used to verify the data.
The iss property in a header is the endpoint of the issuer. Following the endpoint we get:
{
"keys": [
{
"alg": "RS256",
"e": "AQAB",
"kid": "ywdoAL4WL...rV4InvRo=",
"kty": "RSA",
"n": "m7uImGR -TRUNCATED AhaabmiCq5WMQ",
"use": "sig"
},
{...}
]
}
At the first request, a client needs to contact the authentication server, sending username and password to it. If credentials are valid, a JWT token will be returned to the client that will use it to request an API.