JSON Web Token (JWT) and why we use them
By: Rohit Jacob Mathew
Tags: Turtlemint, Security, Authentication, Engineering, Jwt

JSON Web Token (JWT) and how we use them at Turtlemint

So I wanted to talk about how we use JWT here at Turtlemint. What is JWT (JSON Web Token) you ask? JSON Web Token (JWT) is an open standard (RFC 7519) for securely transmitting information between parties as JSON objects.

Let me take you through the whole thing from scratch

Authentication vs Authorization

Authentication is basically what happens when users sign-in. We check the user's identity based on some credentials of their e.g username/password. Authorization, on the other hand, checks if the above-validated user is able to access a certain flow.

Authentication vs Authorisation. Image from ssl2buy

Now I am not going to into all the details of the authentication flow but a generic login form is the simplest example in which the client (e.g -browser) knows that this is an actual user and gets their details. It makes no sense to keep authenticating every single subsequent interaction of the user with a system as this will add extra processing time; and as the saying goes: time is money. Hence, we authenticate and then store specific data based on which we authorize the subsequent interactions.

The simplest solution to enable this authorization flow is session-based authentication. In this, the server will create a session for the user after the user logs in. The session id is then stored on a cookie on the user’s browser. While the user stays logged in, the cookie would be sent along with every subsequent request. The server can then compare the session id stored on the cookie against the session information stored in the memory to verify the user’s identity and sends a response with the corresponding state! This obviously is not an optimal solution when you scale the system and leads to a stateful implementation where we are dependent on a server to authenticate every request.

Sounds good. What does JWT have to do with this?

Good question. So token-based authentication like JWT is a much more scalable solution as JWT is stateless. That means the user state is never saved in the server memory but the state is stored inside the token on the client side itself. By transmitting these JWTs with requests to other parties, you can make those systems more secure too. Lets quickly run through the authentication and authorization flow:

First, the user logs on to the authentication server using an authentication key (it can be a username / password pair, or a Facebook key, or a Google key, or a key from another account). The authentication server then creates the JWT and sends it to the user. When the user makes a request to the application API, he adds the previously received JWT to it. When a user makes an API request, the application can check whether the user is what he claims to be, using the JWT from the request. In this scheme, the application server is configured to be able to check whether the incoming JWT is exactly what was created by the authentication server (the verification process will be explained later in more detail).

Oh, interesting 🤔 So what does a JWT look like?

A JSON Web Token consists of 3 parts separated by periods.

header.payload.signature

Structure of JSON Web Token (JWT). Image from Suresh Kumar

Header

The header typically only contains 2 details: the type of token (JWT in this case) and the hashing algorithm used by the token such as RSA, HMAC, or SHA256. This generally uses HS256 by default.

{

“alg”: “HS256”,

“typ”: “JWT”

}

Payload

The actual data pertaining to a user is what we call claims. These claims can be of 3 types:

Reserved claims: These are some predefined claims which are not mandatory but recommended to use. These help the application judge the authenticity of the token. Some of them are iss (issuer), exp (expiration time), sub (subject), aud (audience), among others. The full list is available here

These are some predefined claims which are not mandatory but recommended to use. These help the application judge the authenticity of the token. Some of them are iss (issuer), exp (expiration time), sub (subject), aud (audience), among others. The full list is available here Public claims: These can be defined at will by those using JWTs. To avoid issues they should be defined in the IANA JSON Web Token Registry. Here is some more information regarding public claims.

These can be defined at will by those using JWTs. To avoid issues they should be defined in the IANA JSON Web Token Registry. Here is some more information regarding public claims. Private claims: These are the custom claims created to share information between parties that agree on using them. Examples could be specific values such as employee ID and department name.

In the below code snippet you can see different types of claims being used where iss is a reserved claim, name is a public claim and admin is a private claim.



[...]

"iss": "

"name": "Rohit Jacob Mathew",

"admin": false

} [...]"iss": " https://rohitjmathew.space ","name": "Rohit Jacob Mathew","admin": false

REMEMBER: Do not put large data in claim sets. Claim sets are meant to be compact. Also, do not put sensitive information, since JWT can be decoded easily.

Signature

The signature is the most important part of a JSON Web Token (JWT). It is calculated by encoding the header and payload using Base64url Encoding and concatenating them with a period separator, which is then run through the cryptographic algorithm.

// signature algorithm

data = base64urlEncode( header ) + “.” + base64urlEncode( payload ) signature = HMAC( data, secret_salt )

So when the header or payload changes, the signature has to be calculated again.

Put Together

Thus the JWT looks like:

token = encodeBase64Url(header) + ‘.’ + encodeBase64Url(payload) + ‘.’ + encodeBase64Url(signature) token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3JvaGl0am1hdGhldy5zcGFjZSIsIm5hbWUiOiJSb2hpdCBKYWNvYiBNYXRoZXciLCJhZG1pbiI6ZmFsc2V9.ZOCcJAceq0Uq3fuIfWA0FVT_BLi5o-iPvyN4rhZgBuo

Securing JWT

I’m sure if you took the above JWT and checked on jwt.io you could see all the data in the token. This brings up the question of how is this secure?

It’s absolutely crucial to know that JWT’s are generally encoded and not encrypted. It is a mechanism by which you can verify that the data is not tampered with and has come from a trusted source.

A simple way in which you can ensure that JWT’s are secure is by ensuring your requests are sent on HTTPS endpoints in which all data being passed in the request is encrypted.

Now, JWT uses two mechanisms to secure the information within it— signing and encryption. The two standards that describe these security features of JWT are JSON Web Signature (JWS) and JSON Web Encryption (JWE). Let me give you a rundown on them.

Signing

The purpose of a signature is to allow one or more parties to establish the authenticity of the JWT. Say I change the values in the payload above on jwt.io and try using it from my client. Well, that’s where we can use JWS to sign the token and let it verify that the data contained in the JWT has not been tampered with.

Now if you remember the signature is basically the encoded header and payload concatenated with a period and then run through a hashing algorithm with a secret key.

This signature attached at the end enables us to determine if the JWT has been tampered with because for any change in the data the signature will change. A signature, however, does not prevent other parties from reading the contents of the JWT. This is what encryption is designed to do.

Encryption

While signing a JWT provides a means to establish the authenticity of the JWT contents, encryption provides a way to keep the contents of the JWT unreadable to third parties.

An encrypted JWT is known as JWE (JSON Web Encryption) and, unlike JWS, its compact serialization form has 5 elements separated by dots. Similar to JWS, it can use two cryptographic schemes: a shared secret scheme and a public/private-key scheme.

Wow, 😮 That's so cool. So how do you use JWT at Turtlemint?

We predominantly use JWT to allow us to transfer data between multiple applications as well as between domains with greater security.

As we have multiple products across multiple domains, this results in us having to transfer data from one domain to another in a more secure manner. A common problem you will see when doing something like this is CORS issues. JWT tokens enable the sharing of these resources in small containers as a part of the API call while also enabling us to validate the data (to be authentic). We also have services that need to interact with each other over the internet and use JWT to pass user-related data between them more securely.

Additional Info

Use the ebook below to better understand JWT. This is provided by Auth0 one of the leading providers of authentication, security, and identity solutions.