JWT vs. Opaque Tokens

OAuth2 relies on tokens for API access, and these tokens come in two common formats: JWT (JSON Web Tokens) and opaque tokens. Each approach has different trade-offs in terms of security, validation, and usability. Understanding the differences will help you make the right choice for your application.

Understanding JWTs and Opaque Tokens

A JWT is a self-contained token that carries its own data, including claims about the user and expiration times. It is signed to prevent tampering and can be validated locally by an API without needing a database lookup. This makes JWTs efficient in distributed systems, where APIs need to verify tokens quickly without relying on an external service.

On the other hand, an opaque token is simply a random string with no embedded data. When an API receives an opaque token, it must contact an external service or database to validate its authenticity. This extra lookup adds overhead but provides a key advantage: opaque tokens are much easier to revoke.

How JWTs Work

JWTs follow a structured format with three parts: a header, a payload, and a signature. The header contains metadata about the token, such as the signing algorithm. The payload holds claims, including user identifiers, roles, and expiration timestamps. The signature ensures that the token has not been tampered with. Since JWTs are self-contained, they can be validated without a database lookup, making them a popular choice for stateless authentication.

For example, a JWT might look like this:

{
  "iss": "https://idp.example.com",
  "sub": "user-123",
  "aud": "api.example.com",
  "exp": 1714759200
}

In this structure, the iss (issuer) indicates which authentication service issued the token, sub (subject) identifies the user, aud (audience) specifies the API that should accept the token, and exp (expiration) defines when the token becomes invalid.

The Strengths and Weaknesses of JWTs

One of the main advantages of JWTs is that they do not require a database lookup for validation. APIs can simply verify the signature using a public key and immediately determine if the token is valid. This improves performance, especially in microservices architectures, where multiple services need to authenticate requests quickly.

However, JWTs also come with drawbacks. Since they are self-contained, they cannot be revoked individually once issued. If a JWT is compromised, it remains valid until it expires. This is why short expiration times are recommended when using JWTs. Additionally, JWTs can become large if too many claims are included, increasing bandwidth usage in API requests.

How Opaque Tokens Work

Unlike JWTs, opaque tokens contain no readable information. They are simply random strings that serve as a reference to a stored session. When an API receives an opaque token, it must contact an external validation service (such as an OAuth2 introspection endpoint) to determine whether the token is active and which user it belongs to.

This lookup process might seem inefficient, but it offers better security in some cases. Because the API does not rely on self-contained claims, the authentication server retains full control over token validation. If a user logs out or their session is revoked, the token is immediately invalidated in the database, preventing further access.

A typical opaque token might look like this:

"mF_9.B5f-4.1JqM"

Unlike JWTs, this token provides no context about the user or its expiration time. The API must validate it externally before granting access.

When to Use JWTs

JWTs are useful when you need stateless authentication and fast validation. They work well in microservices environments, where multiple APIs need to authenticate requests without relying on a central database. JWTs also allow embedding claims, which can reduce the number of API calls needed to fetch user information.

However, JWTs are not a good fit when immediate revocation is required. If a user’s access needs to be revoked instantly, JWTs alone are insufficient unless paired with an additional revocation mechanism.

When to Use Opaque Tokens

Opaque tokens are a better choice when you need strict session control. They allow authentication servers to retain full control over token validity, ensuring that tokens can be revoked at any time. This makes them ideal for scenarios where security takes precedence over performance, such as banking applications or enterprise systems with strict access control policies.

The trade-off is that opaque tokens introduce latency, since every validation requires an external database lookup. In high-performance applications, this can become a bottleneck.

A Hybrid Approach

A common pattern is to combine both approaches: using JWTs for access tokens and opaque tokens for refresh tokens. In this setup, JWTs provide fast authentication for API requests, while opaque refresh tokens allow the authentication server to revoke sessions when needed.

For example, in this model:

  • The access token (JWT) is short-lived (e.g., expires in 5 minutes).
  • The refresh token (opaque) is stored securely and used to obtain a new access token.

By using this hybrid approach, you get the best of both worlds—fast API authentication with JWTs while maintaining control over long-term sessions with opaque tokens.

Final Thoughts

There is no one-size-fits-all solution when choosing between JWTs and opaque tokens. The right choice depends on your application's requirements. JWTs are great for performance but lack built-in revocation. Opaque tokens are more secure in terms of session management but introduce additional latency.

For most modern OAuth2 implementations, a hybrid model is the best option, balancing speed and security effectively.


I'm currently writing a book called React Router OAuth2 Handbook, focused on implementing secure OAuth2 authentication in Remix and React Router apps—using patterns you can apply to any web app.

The landing page is live (book coming soon) at books.sergiodxa.com