Why JWT in most OAuth 2.0 services

This article explains why JWT is widely adopted as the format for access tokens in OAuth 2.0, highlighting its benefits and limitations.
Yijun
YijunDeveloper
September 11, 20238 min read
Why JWT in most OAuth 2.0 services

OAuth 2.0 is widely used today. As a core framework for authorization services, one of OAuth 2.0's main responsibilities is to issue access tokens for users. We have noticed that many OAuth service providers in the market issue access tokens in JWT format.

In this article, we will introduce what JWT is and why it is extensively adopted as the format for access tokens issued by OAuth 2.0.

Introduction to JWT

JWT stands for JSON Web Token, and it’s is defined by RFC 7519 as follows:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.

This definition makes it clear that JWT is a token used to pass claims between different parties.

Because JWTs are passed among multiple parties, they are signed to ensure the integrity and authenticity of the data.

A signed JWT has the following format:

[header].[payload].[signature]

It consists of three parts separated by .: the header, payload, and signature.

Here is an example of a real-world JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

You can try parsing it at https://jwt.io:

Decode JWT in jwt.io

As shown in the image, the header section of the JWT contains information about the signing algorithm used and the token's type. The payload section contains the claims carried by the JWT, and the signature is used to verify the integrity of the JWT.

Now that we understand what JWT is and the meanings of its different parts, let's proceed to explain why many OAuth authorization services choose JWT as their access token.

Benefits of using JWT

The key distinctions between JWT and traditional randomly generated string-based tokens are that JWTs can carry information and can be validated through decoding. These differences bring two significant advantages:

  • Resource Efficiency: JWTs can carry information about the user or session, eliminating the need for frequent database lookups. This efficiency can reduce the resource consumption of services.
  • Improved Availability and Scalability: JWTs reduce the reliance on server-side state management. This allows services to be more stateless, enhancing their availability and scalability.

When using traditional random string-based tokens, the typical process for verification and authentication is as follows:

Auth ServerResource ServerUserAuth ServerResource ServerUser(1) Request resources with a token(2) Request to validate the token(3) Validate token & retrieve user info by the token(4) Return token related user info(5) Retrieve user resources by user info(6) Resources

As shown in the diagram, when a system has numerous users and many different Resource Servers, it can result in numerous token validation requests to the Auth Server.

Over time, as the system grows, the Auth Server can easily become a bottleneck, posing a challenge to the overall service availability.

However, when JWTs are introduced, the validation process changes to:

Resource ServerUserResource ServerUser(1) Request resources with a JWT(2) Verify and get user info from the decoded JWT(3) Retrieve user resources by user info(6) Resources

Thanks to the feature of JWTs that allows for validation through decoding, the Resource Server can verify the integrity of JWTs and extract user information from them without the need to interact with the Auth Server (For details on decoding and validation of JWTs, you can refer to the Logto documentation).

Limitations of JWT

While JWTs offer significant advantages in modern software architectures, they also have limitations to consider.

Easily snooped payload

As mentioned earlier, a JWT consists of three parts: the header,payload, and signature. How are these components generated? Let's take the JWT from the previous example and demonstrate the JWT generation process:

const headerData = {
  alg: 'HS256',
  typ: 'JWT',
};

const payloadData = {
  sub: '1234567890',
  name: 'John Doe',
  iat: 1516239022,
};

const signingKey = 'PRIVATE_SIGNING_KEY';

// Generate header part
const header = base64(JSON.stringify(headerData));

// Generate payload part
const payload = base64(JSON.stringify(payloadData));

// Generate signature part
const signature = base64(signingAlgorithm(header + payload, signingKey));

const jwt = `${header}.${payload}.${signature}`;

As shown in the code above, the JWT's header and payload are simply encoded as base64 strings.

This means that as long as someone has access to the token, they can easily decode the base64 string of the JWT payload and access the information it carries. Conversely, it's also relatively easy to forge a payload and replace the original JWT's payload with a manipulated one.

While it's true that the payload of a JWT can be relatively easily forged, it's important to note that the signature part of the JWT cannot be replaced with forged content, as it requires the secret signing key. Therefore, without the correct signature, the JWT cannot pass validation.

So, when using JWTs, it's important to keep the following considerations in mind:

  1. Always use SSL: To ensure that JWT information is not leaked during transmission, it's essential to use SSL (Secure Sockets Layer) or its successor, TLS (Transport Layer Security), to encrypt the data in transit.
  2. Avoid storing sensitive data: It's not recommended to store sensitive data in the JWT payload. The payload can be easily decoded, as mentioned earlier, and should primarily contain non-sensitive, relevant claims.
  3. Validate JWTs: Before relying on the information contained within a JWT, ensure that it has passed a valid and secure validation process, including verifying the signature and checking for token expiration. This helps prevent the use of tampered or unauthorized tokens.

Hard to revoke

In general, access tokens usually have an expiration time. If the access token is represented as random strings without any information, we can check whether the token has been revoked during each validation in the Auth Server.

As for JWTs, due to JWTs containing expiration information within themselves, and the fact that JWT validation doesn't rely on the Auth Server, once an Auth Server issues an access token in JWT format, it becomes impossible to change the token's state during its usage.

After a JWT token naturally expires, we can obtain a new JWT from the authorization server using a refresh token (you can refer to Logto's blog for information on refresh tokens).

However, in certain situations, such as when a user revokes authorization or changes their password, and you need to revoke an already issued but not yet expired token, there is no straightforward solution available.

There are two common approaches to mitigate the impact of token revocation midway:

  1. Set a shorter expiration time for the access token and rely on the token refresh mechanism to promptly refresh the token's status.

Because the access token has a shorter expiration time, when a user discovers that the access token has expired, they can request a new access token by a refresh token from the authorization service. This way, the token's status on the user's side can synchronize with the backend as soon as possible. However, this approach comes with additional overhead, which users need to consider.

  1. Maintain a revocation list for access tokens and check whether the token is on the list during each validation.

This method has certain limitations. One of the advantages of JWT is that it doesn't require the server to store state information, and JWTs are typically stateless. However, maintaining a revocation list necessitates effective storage and maintenance, relying on additional storage mechanisms. This essentially sacrifices the advantages of JWT and can potentially lead to performance issues. Therefore, the token revocation mechanism needs to be implemented by developers in a way that is suitable for their specific use case.

Summary

In this article, we provided a brief introduction to JWT, highlighting its advantages and limitations. By now, you should have a deeper understanding of JWT and the scenarios in which it is commonly used. While JWT has its challenges, the benefits it brings when used as the token format in OAuth 2.0 services far outweigh its drawbacks.

Logto, as a rapidly growing identity authentication service, also employs JWT as the format for its access tokens. It strictly adheres to various authorization and authentication protocols, making it exceptionally easy to integrate identity authentication services into your products. Logto have officially launched its SaaS service, and you can try it for free today.