Exploring The JSON Web Token (JWT)

What is a JWT?

The JSON Web Token is a safe way to transfer JSON data through a URI query string, HTTP header, or other transport means. This is a great alternative to maintaining session state without session variables and the explicit need for a database to lookup sensitive information.

The token is ‘safe’, because the JSON string object is encoded to Base64url. The base64 encoding ensures the data remains intact and isn’t modified or interpreted differently between systems. Url encoding ensures spaces are interpreted correctly and characters that have special meaning such as ‘?’ or ‘&’ are unambiguous. Two additional features add to their safety… ‘Signatures’ help ensure the data sent has not been tampered with or changed in any way. Encrypted payloads help ensure the source of the data and hides the meaning of the contents of that data.

A token combines these 3 parts with the dot ‘.’ as its separator where the layout is

header.payload.signature

The header contains information about the token which should be shared to describe information such as the cryptography used to encrypt the payload.

Example:

{"typ":"JWT","alg":"HS256"}

This header describes the type of JSON object as JWT and is hashed using HMAC SHA-256. This means the token will have a signature to help prove it’s authentic and hasn’t been tampered with. A secret-key is used with the hashing algorithm to produce the signature. If a signature is not used, alg will be set to none. There are some security concerns to keep in mind with this.

Creating a JWT

Creating a JWT is easily done by using existing libraries and there are options available for many programming languages. Let’s experiment on the Linux command line to get an understanding of the basic construction.

Base64 Encoding

Base64 encode the header

echo -n '{"typ":"JWT","alg":"HS256"}' | base64

Result:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

In some cases, the result will have one or two trailing = which is Base64 encoding padding and according to the JWT spec, should be removed. The -n option for the echo command removes the trailing newline which we don’t want to include in our token.

Next we’ll base64url encode the payload. The reason this now becomes a requirement is because of the space in “Software Developer”. The payload is also known as the claims. Here is the bash recipe to base64url encode a string that I’ll use here in this example.

Tamper Proof JWT With A Signature

While we have a JWT that will work, we can’t be sure it hasn’t been modified during transit. To do this, the JWT can be signed using the hash algorithm we’ve specified in the header. To sign this, we’ll take the base64 encoded token we have thus far, and hash it using the openssl library with our secret-key of “ABC”.

Verifying a JWT With The Signature

Once we’ve received the JWT, we can use the secret-key to hash and verify that our resulting signature matches the signature in the token. This is done by simply repeating what we did during signing, and then verifying the signature is a match.