JWT for Dummies (OK, not 100% dummies)

We need to secure API.
One common way to secure this is using token, some long-character-sequence, attached on HTTP request (the good practice is in HTTP request header), where API server (or API gateway) validates the token against some database.

There are two types of tokens:

  • stateful : where server save the token data (e.g. on Redis), and validates each request against this token
  • stateless : in the contrary, server save nothing. The token itself contains all information required for validation.

There is a common way to create stateless tokens, using JSON web token, or JWT.
In simple words, it is a string consists of 3 parts. Each part separated by dot.
1st part is header.
2nd part is payload.
And 3rd part is signature.

JWT structure

The header is a JSON object containing information about how the JWT signature should be computed. This header sometimes called as JOSE (Javascript Object Signing & Encryption)
In sample above, there are two fields for header JSON object.

  • “typ” which value is “JWT”
  • “alg” which shows hash algorithm to create JWT signature component.
    In this example, we use HMAC SHA 256 to calculate signature.
    The 1st JWT token component, is base64 encode of this JSON object.

Payload is JWT component which is JSON that contains “claim” data. This data is used by consumer to claim that this information belongs to consumer.
There are several standard “claim” field as defined on RFC-7519 about JWT. We can also add as many custom claim as we want.
Note that this payload, is not the payload for transaction data, but payload used for JWT token.
These claims must be validated on the API side, or if using api management, on api management side
In example above, we have two claims : the issuer of the token, and the token expired date is epoch time in second.
Epoch time is a number of seconds since January 1, 1970.
To calculate epoch time, you can use online tools like epochconverter.com or time library on most programming language.
The 2nd JWT token component, is base64 encode of this claim object.

In signature, the 3rd component, we hash the first two parts of JWT which is base64(header) and base64(payload), with . (dot) to separate them.
This component is hashed using algorithm in header part, and encrypted using secret key for specific consumer.
Unless someone has the secret key, they can not decrypt this information, so this is where JWT goes secure.
In this example, we hash using HMAC SHA256 algorithm, as defined in header.
And the secret key is mySecretKey123.
The 3rd JWT token part, is hashed string, in base64 encode

Using previous example, we will get JWT token like picture below. This JWT token can be calculated by using libraries, or online JWT calculator. See website jwt.io for calculator or list of libraries for many programming language. We can then attach this token as authorization mechanism. In this case we can use HTTP “Authorization” header with value “Bearer token”.

Calculated JWT token

Being widely used, JWT also provides standard fields for first part, the header, and also second part, the payload. Being standard doesn’t mean we have to use all of them. Some fields are optional, and we can also add our own field, usually on the payload part.

These are standard fields for header. Notice the note on yellow rows, where using the field will make JWT vulnerable.

JWT Header standard fields

Below is some sample for header. Note that fields order is not important. Notice the green sample, where we use kid or key id field. Also notice the red sample, where we put the HMAC key on the header, field “jwk”.

It is a good practice to change keys regularly, or use multiple keys. When having multiple keys for HMAC, we can put the keys on server. This can be file, database, et cetera. For each key, we have key id. On the JWT header, we specify which secret key to use for HMAC on “kid” field.

kid field in JWT header

JWT specification also provides two standard fields : jwk and jku, which basically to tell the server : use this secret key, or you can retrieve secret key in this location. Using this fields means we give secret key, something that supposedly secret, over the network. So an attacker that intercepts the communication will easily retrieve the valid HMAC key and reuse it to generate fake JWT tokens. Although HTTPS can secure some part of this, its useless if attacker herself is valid user and intercept traffic from her own computer. Since hmac key generally same for all other tokens, having one secret key for attacker can be enough. That’s why, using jwk or jku means making JWT token vulnerable.

jwk, jku, and security vulnerability

These are standard fields for payload. These fields usually called as claims.

Other than the standard payload fields, or usually called as standard claims, we can also has our own fields, depends to our own need. It is called as private claims. For example, we can have these private claims

This is some sample for payload. Note that fields order is not important. Basically we can use any private claims, but doesnt mean we have to put all of our business fields in JWT tokens.

Sample JWT payload

In the payload, we have several fields for time validation : not before (nbf), and expired at (exp). Since we talk about networks, there might be a clock skew, or time difference, from one node to another. This time difference can means one node clock is faster or slower than the other. For example, client clock is currently 10:19, but server clock is already at 10:21.

Server is responsible to validate these time fields. During server validation, it is better to give time tolerance to handle the clock skew. This tolerance should be no more than few minutes. This time tolerance is usually called as leeway.

For sample code on JWT and encrypted JWT (JWE), see here.

Cheers

--

--