JSON Web Tokens (Part 1)
Tags: jwt, node, authentication
Published: 2020-02-04 10:01:54

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

In this post I would like to explain how can we use JWTs for authentication in web applications. In the next part, we will be using `NodeJS`, `Express` and `jsonwebtoken` library for implementing a simple JWT based authentication. Note that, we would use the word system and server interchangeably.

So, a JWT looks typically like this:

<center>

![JWT](https://dev-to-uploads.s3.amazonaws.com/i/8cgd55dhl60n8o430f1e.png)

Image Source: [jwt.io](https://jwt.io/)

</center>

So, this token can be broken down into 3 parts each separted by a **`.(dot)`**

- Header (Red colour)
- Payload (Pink colour)
- Signature (Light Blue colour)

The header and payload sections are just normal JSON strings that is encoded in **[base64](https://en.wikipedia.org/wiki/Base64)**. Now, there is a difference between `encoding` and `encryption`. Encryption is when you use a secret key to transform message into a cipher which can only be transformed back to original message if you have the key. But in encoding, we just transform the message into a format that is easy to transfer between computers. Anyone with an encoded message can transform it back and read its content(there is no key involved).

If you use a [base64 decoder](https://www.base64decode.org/) for decoding the header or payload section here is what you get,

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

```json
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
```

Third and final part, signature is also `base64` encoded but if you try to decode it, you would get a gibberish text.

### Header

Header section contains some information about the nature of this token. For example, in the particular token above, `typ` contains information about the type of this token(which is JWT) and `alg` says that the algorithm used to sign this token that is `HMCASHA256`.

> Note: We will explain what does _sign_ means later in this post. But for now you can take the analogy of _signature_ that people do on documents to say _that I have verified it and I approve of it._

### Payload

Payload section contains of a set of `claims` that a party makes with this token. So, the contents of payload section says when, where, why and by whom this token can be used. Again continuing with the example given, `sub` stands for **subject** and it contains information about whom is this token concerned with, `name` is evidently name of the person and `iat` means **issued at**, It is Unix timestamp of the moment when this token was issued.

> Side Note: Unix Timestamp is number of seconds that has passed since January 1, 1970. considering that every day has 86400 seconds. Also since this is calculated relative to UTC, it is same for all computers around the world.

> Side Note: You will come across names John Doe quite frequently if you read posts like this. This is the frequently used name to refer to a male whose name is not known or is being concealed. Jane Doe is used for females.

Now there are certain standard claims that is specified in [RC 7519](https://tools.ietf.org/html/rfc7519) for a particular purpose:

- iss (issuer): Issuer of the JWT
- sub (subject): Subject of the JWT (the user)
- aud (audience): Recipient for which the JWT is intended
- exp (expiration time): Time after which the JWT expires
- nbf (not before time): Time before which the JWT must not be accepted for processing
- iat (issued at time): Time at which the JWT was issued; can be used to determine age of the JWT
- jti (JWT ID): Unique identifier; can be used to prevent the JWT from being replayed (allows a token to be used only once)

Now before we get to the third and most important part of JWTs, let us first consider a scenerio where JWT is used for user authentication.

Consider how user's are authenticated normally(that is without the use of tokens). So, when user logs in for the first time, he gives an username and password. The system checks if username and password is correct. If it matches with the database records, then systems creates a random string (called session identifier), stores it in the database along with user's identification and sends the identifier back to the user.(It is usually send as a cookie, but that does not matter for our disscussion)

Next time when user visits the website, he sends this identifier along with the request. When system recieves this identifier, it matches that with information in the database. If the identifier matches, then the system knows that user is genuine. To log out a user, system simply deletes this identifier from the database.

<center>

![Session based authentication](https://dev-to-uploads.s3.amazonaws.com/i/t5ozjwmmkvyrvcnk6f6u.png)

Image Source: [Medium](https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4)

</center>

Now why does the system believes in this identifier? The reason is that this identifier is usually a long and random string. So, it is not possible for anyone to know it. Also if someone tries to randomly generate all the possible tokens, it might take him 10<sup>18</sup> billion years to test every combination.(Assuming that identifier is 128 bits long and it takes 1 second for testing 10,000 strings) For reference, current age of universe is 13.8 billion years.

There are few problem with this session based approach though. First one which is that for every request the system needs to hit database to check if `session identiifer` is valid. (This is problematic because database access takes time) Other similar but related problem is with microservice architecture. In this case, identifiers need to be stored in a central server, because different servers need to access this information.(Therefore, this would take even more time and is much more difficult to manage) Both of this problems can be solved with the help of the JWTs.

So in the case of JWTs, when user first logs in the system generates one of this tokens and send it to the user. The claims that system usually put in this token is `sub` to identify the user and other details like the user's privilege level. So, when user makes a request to the server, then system checks if the token is well formed JWT and just by decoding the payload section it can verify the user which this token identifies.

<center>

![JWT based authentication](https://dev-to-uploads.s3.amazonaws.com/i/0206uz1lkv14rd95smo6.png)

Image Source: [Medium](https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4)

</center>

Now, the only problem is anyone can generate this token. (Remember that header and payload are just encoded) So, anyone in this world can generate a token containing anyone else's identification and send it to the server. The system would then not be able to distinguish wether the token came from the right person or someone else. This is the place where the signature comes into picture.

### Signature

Signature is used to verify that this token (JWT) is issued only by the server and no one else could generate it.

The idea is very simple. Each system has a long and unique `secret key` with itself. This key cannot be guessed by anyone else. (Because of similar reasons of session identifier) When the system generates a token it then sends it through a Message Authentication Code Algorithm(HMACSHA256 is one of them. There are many others) along with the secret key. Now this algorithm gives a pattern of bits as its result. This bit pattern is then encoded into base64 format to form the signature.

The bit pattern(which we will call signature from now) given out by the algorithm is not random but it has two important properties.

- Given the signature, one cannot guess the value of secret key or the contents of the message.(This is to say that the algorithm computes a one-way function)
- Second if we change the contents of message or the secret key even slightly the signature would change completely.

This two properties make sure that only way to guess the correct signature for any given message is to randomly try all possible combination. (Which would again take 10<sup>18</sup> billion years) Therefore it is highly unlikely that anyone would be able to do it.

> Note: Scientists say that sun would burn out within 4-5 billion years from now.

Now, when someone sends this token back to the server, it just generates the signature again using the same key and algorithm. If the resulting signature matches with the signature that came with the token, then server can be pretty sure that this is a valid token.

> Note: For this particular `HMACSHA256` algorithm the signature is 256 bits long. If you want a rough idea of how unlikely it is to guess a signature watch this [3Blue1Brown video](https://www.youtube.com/watch?v=S9JGmA5_unY).

I hope that you have an idea of how JWT is used. I feel that this post is getting a bit long. So, we will continue with how to implement JWT using NodeJS in next part of this post.

You can verify the example signature using [jwt.io](https://jwt.io/). Just enter the header and payload given above. The secret I used is `hello`.

References:

1. [https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519)
2. [https://jwt.io/introduction/](https://jwt.io/introduction/)
3. [https://en.wikipedia.org/wiki/HMAC](https://en.wikipedia.org/wiki/HMAC)
4. [https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication](https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication)
5. [https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4](https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4)