For a long time, user authentication on the web consisted of storing pieces of very simple data (like a user ID) in the user's browser as a cookie. This worked pretty well – and still does for many applications – but sometimes you require more flexibility.
Traditionally, to get this flexibility you had to store 'state' on the server, which might tell you things like who the user is, what kind of permissions they have, etc. To store this data, you usually had to have a dedicated data store, like Redis or a database, which added to the complexity of your application.
In the past few years, a new open standard has come along that's increasingly being adopted by some of the top websites and applications. This standard is the JSON Web Token (JWT). Throughout this article, we'll show you how it works, and more importantly, why you'd actually want to use it.
What is JWT?
A JSON Web Token (JWT) is a safe, compact, and self-contained way of transmitting information between multiple parties in the form of a JSON object.
Say you want to log in to an app, like say Instagram. Instagram allows users to log in using their Facebook profile. So when the user selects the option to log in using Facebook, the app contacts Facebook’s Authentication server with the user’s credentials (username and password).
Once the Authentication server verifies the user’s credentials, it will create a JWT and send it to the user. The app now gets this JWT and allows the user access to its data.
Although JWT is commonly used for managing authorization, the idea behind JWT is actually something else – the exchange of information! There’s an open industry standard specification called RFC 7519 which outlines how a JWT should be structured and how to use it for exchanging information, or claims, as they’re usually called. But since JWT is so widely used for authorization, let’s focus our attention in this article to just that.
Anatomy of JWT
The header typically consists of two parts: the token’s type, and the hashing algorithm that is being used.
The payload is where the actual information that we want to send is stored. Here is an example of a simple payload. Know that payloads can be way more complicated than this to ensure better security.
"name": "John Doe",
The signature is used to verify that the message was not altered before reaching its destination. This is usually done by using private keys.
base64UrlEncode(header) + "." +
These three parts are usually encoded into three Base64-URI strings that are separated by a ‘.’ in between them.
How JWT Authentication Works
Authentication using JWT is quite simple. Let’s see the following (simplified) workflow that explains JWT authentication.
- A user inserts their login data in the application or a trusted authentication service.
- In case of successful authentication, the service grants a token to the user containing information about this user (unique identifier, full name, role, etc.)
- When further addressing the application, such as calling API calls, the token is transferred in the user’s requests (in cookies, request headers, post or get parameters, etc.)
- After receiving the token, the application verifies its signature. Making sure the signature is valid, the application extracts the user’s data out of the payload part and authorizes the user. Assuming that the user data is valid (JWT token data is verified), the server returns a response for the requested API call.
What’s so special about JWT?
As we got to know the makeup of a JWT token, you might have been thinking about what makes it so special compared to other authentication methods, especially session-based authentication.
Based on official JWT documentation, the most important characteristic of JWT that makes it special is its statelessness. We saw what sort of data can be stored in a JWT in the previous section, and all the data that is needed to verify the token and identify the user is stored in the token itself. There is no need to maintain any record of the token in the server, like storing the token in a database as we do with sessions. This makes JWTs stateless.
This stateless nature gives us the biggest benefit that comes with JWTs: The server that issues the JWT and the server that validates it does not have to be the same one. One server can issue JWTs and carry out authentication tasks, while the other server that implements application logic can validate the JWT independently of the first server.
In the age of API backends and microservice architecture applications, this allows developers to delegate all authentication tasks to one server while the others implement application logic and decouple the system as much as possible.
When JWT issuing and validating is carried out by separate servers, using a public-private key system is the best approach to take. In this case, the private key should be stored securely in the authentication server.
JWT is a modern and robust solution to authenticating users and sharing sensitive information while not maintaining state. A JWT is made of three parts: header, payload, and signature. Despite the benefits of JWTs in modern application development, there are special measures we need to take to ensure the security of the tokens and user data. Sending JWTs in cookies instead of in the header, shortening their expiration time, and using refresh tokens to issue new access tokens are some of the security measures we can take to guarantee the security of our application, its users, and their data.