Intro to JWT - Step by Step
Tags: jwt, rest, beginners
Published: 2021-03-10 19:18:21

In this article I will be giving you an introduction about JWT. 

You can watch full video on Youtube:
{% youtube U8HnsWU5zkE %}

So what we will cover today:

- What is JWT
- When should we use it
- JWT vs Session Id
- JWT structure
- JWT Signature

Please like, share and subscribe if you like the video. It will really help the channel

## What is JWT

JWT (Json Web Token) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

So in simpler terms its an encrypted string in json format that contain sensitive information which allow us to verify the sender between different services

## When should you use JWT?

- **Authorisation**: This is the most common scenario for using JWT. JWT is used for authorisation not authentication. With **authentication** we are verifying that the username and password are valid, we are logging the user into the system. With **authorisation** we are validating that the requests that's being sent to the server belong to the user who has logged in during the authentication, we are authorising that this user has access to the system basically allowing the user to access routes, services, and resources that are permitted with that token.
- **Information Exchange**: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.

### Session Id vs JWT

Small Web Apps

**Session Id Implementation**

In traditional web applications we use sessions to authorise the users, once the users logged-in into the application we assign a unique session id for user. We save this session id in a secure cookie in the user browser and in the server memory. We keep using the same session with every request so the server knows the user is authenticate. With every request the session id in the cookie is matched with the session id in the server memory to verify that the user is authorised

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84otxwg46ca7few4uumu.png)

**Implementation with JWT**

In JWT implementation we use JWT to authorise the users, once the users logged-in into the application will generate a unique JWT for every authenticated user. We save the token in local storage or cookie in the browser, but we don't save anything on the server side .With every request the token is sent to the server to be decrypted and validated to verify that the user is authorised, if the token is manipulated in anyway its rejected

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2lp802k2ngwd8e1q89n.png)

These implementations are fine for small sites, but we can already see some benefits in JWT by reducing the load from server since we are not storing the session id anymore. 

Advance Web Apps (Multiple Servers)

What happens if our application grew in popularity and we need to scale our application.

**Session Id Implementation**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zarkuqxz7wesrrhk70o1.png)

We need to have a new server connected to a load balancer to navigate traffic between web servers based traffic and availability. This implementation introduce a new a new problem for us, which is the following

What happens if user 1 has logged in with server 1 and server 1 has saved the session in its memory, when user 1 makes another request and the load balancer redirects the request to server 2 and server 2 doesn't have that session information saved.

The user would be logged out of the application and be asked to sign in again, which is not a good user experience. The way we fix this but introducing cache

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8lxanumcdv45f35xv8r.png)

All sessions now will be saved as well in the cache, so either servers can check if this session exist and can utilise it to verify the user and grant them access to the application. 

Although cache fixes our problem but this solution become very costly in a production environment

- a lot of RAM, CPU, Storage to keep track of all of those sessions as well as processing the requests smoothly.
- Maintaining the cache to make sure there is no ghost sessions or invalid ones
- In case a server crash all sessions are lost which are not synced with cache
- Invaliding users is more complicated
- Hosting cost is high

**Implementation with JWT**

Let us look on how we can approach the same situation with JWT implementation 

Instead of using session ids in cookies and session matching in the server memory; we can use JWT to do this instead. So when the user sign in to our application the server will not generate a session id and save it in memory instead it will create a JWT token and it will encode and serialise it and signs it with its own encryption mechanism. This way the server will know if it got changed or manipulated it will become invalid. And this is being checked since it has been signed by the server encryption mechanism. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/um8jxvtjb4jegxhx1m3z.png)

Scalability is much easier to manage with JWT as we don't require the server to handle any session checks or cache check. Requests can go to any server the load balancer assign it without the need to worry about session availability. Incase 1 server fails all tokens will still be valid as the encryption mechanism is the same on all servers.

Let us do a quick summary on JWT vs SessionId

JWT

- Nothing is saved on the server, its stored in the client inside the JWT
- Encrypted and Signed by the server
- Token contain all the user information
- All information are stored in the token itself

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7p0gf86zx7g33d41dizy.png)

Session Id

- Session id is saved on the server
- Encrypted and Signed
- Session id is a reference to the user
- Server needs to lookup the user information and do the required checks

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35hjaqcgtqoc4fs9lq3u.png)

### JWT structure

JSON Web Tokens consist of three parts separated by dots (`.`), which are:

- Header
- Payload
- Signature

Therefore, a JWT typically looks like the following.

xxxxxx.yyyyyyy.zzzzzzzz

This separation will make it visually easier to see the different part of the tokens. Let's break down the different parts.

**Header**

The header *typically* consists of two parts: 

- the type of the token, which is JWT,
- the signing algorithm being used, such as HMAC SHA256 or RSA.

For example:

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

Then, this JSON is **Base64Url** encoded to form the first part of the JWT.

**Payload (Data)**

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: *registered*, *public*, and *private* claims.

- **Registered claims**: These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of them are: **iss** (issuer), **exp** (expiration time), **sub** (subject), **aud** (audience), and others.
- **Public claims**: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
- **Private claims**: These are the custom claims created to share information between parties that agree on using them and are neither *registered* or *public* claims.

An example payload could be:

```json
{
  "sub": "221122112",
  "name": "Mohamd Lawand",
  "admin": true,
  "exp": 15323232,
  "iat": 14567766 // When the token was issues
}
```

The payload is then **Base64Url** encoded to form the second part of the JSON Web Token.

> Do not put secret information in the payload or header elements of a JWT unless it is encrypted.

### **Signature**

This will allow us to verify that the token is valid and no changes has been done to it. The way it works it takes the first 2 parts of the token, it will encode the header to base64 and do the same for the payload. Then it will concatenate it with a "." so that way we have all of the data that we have shared with the user.

Then it will take the algorithm provide and apply it on the first part. If the result of hashing the first couple of parts match the 3rd section of the token it means the JWT is valid. if it didn't match it shows the token has been edited and its invalid.

The only way to compromise this is making the secret key available anywhere other than the server. But if we keep the secret safe nothing can compromise the process.

```
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
```

The signature is used to verify the message wasn't changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.

This works alot similar to password hashing, where we have 2 parts that are combined and we are using certain algorithms to do 1 way hashing, and then we are comparing the outcome of the hash together to see if they are valid or not. 

### Signing the keys

So now lets discuss JWT in more details, first how JWTs can be signed by

- a secret (with the HMAC algorithm)
- a public/private key pair using RSA or ECDSA.

Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties.

Thank you for reading