devxlogo

Understanding JWTs (and When Not to Use Them)

Understanding JWTs (and When Not to Use Them)
Understanding JWTs (and When Not to Use Them)

Imagine you are building an API or a microservice based backend. You want authentication that works across services, scales easily, and avoids storing session data on a central server. That is when many developers reach for JSON Web Token (JWT). JWTs promise a streamlined, stateless way to carry user identity and authorization claims around, although they also bring sharp tradeoffs. Use them with eyes wide open.

Here is a clear, honest breakdown of what JWTs are, why they work, and the scenarios where they can cause more trouble than they solve, along with how to decide if they are right for your system.

What is a JWT (in plain terms)

A JWT is a compact, URL safe string that encodes a JSON object with claims such as user ID, roles, or permissions plus a signature that proves the data has not been tampered with.

Concretely, a JWT looks like this:

xxxxx.yyyyy.zzzzz

The header declares metadata, for example that it is a JWT and what algorithm is used for signing.

The payload carries the claims, which can include standard fields such as issuer, subject, expiration, audience, or issued at, along with custom data such as user ID, roles, scopes, or tenant ID.

The signature ensures integrity. With the server’s secret or private key, recipients can verify that the token was issued by you and that no one modified it.

Because JWTs embed identity data directly, services receiving a token do not need to check a central session store. This makes JWTs stateless, portable, and scalable, especially for APIs, microservices, mobile clients, or single page apps.

Why JWTs look so attractive (and common uses)

JWTs shine when you need:

Scalable, distributed authentication: In microservices or distributed APIs, JWTs remove the need for a central session database. Each service can independently verify the token.

Statelessness across requests: No server side session storage is required. After login, the client holds the JWT and sends it with every request.

Cross domain or cross service identity propagation: JWTs work well for single sign on, mobile apps, or third party integrations where identity must move across boundaries.

Performance: Because there is no database lookup for each request, response time can be lower, especially during heavy load or inside large distributed systems.

See also  How to Scale WebSocket Connections in Production

In short, when you need a portable and self contained identity token inside a distributed and decoupled system, JWTs often deliver.

Where JWTs introduce risk and complexity (what often goes unsaid)

JWTs are not inherently secure or simple. Their advantages come with tradeoffs. Here are the major downsides you should understand.

Tokens are readable and often not encrypted

By default JWTs are signed, not encrypted. Anyone who obtains the token, for example through network interception or a local storage leak, can decode the payload and read everything. Sensitive data should never be placed inside a JWT unless you encrypt it.

Revocation is hard and statelessness makes it harder

Once issued, a JWT remains valid until it expires. If a user logs out or you need to revoke access, the token is still valid unless you track and reject it manually, which means reintroducing server side state.

This removes one of the core benefits of JWTs if you need real session control such as logout, role changes, or forced invalidation.

Implementation mistakes often create vulnerabilities

Misconfigured libraries or incorrect usage can create serious security holes. Older security issues even let tokens with alg set to none bypass signature checks.

Another recurring problem appears when tokens are stored in localStorage instead of secure HttpOnly cookies. Malicious JavaScript or XSS attacks can easily steal them.

Size and bandwidth overhead

JWTs contain JSON and a signature, and are often much larger than simple opaque session IDs. For mobile clients or heavily trafficked services, this size difference can matter.

The mistaken belief that no state means no server

Many teams adopt JWTs to avoid server side state. Real world systems usually need some form of state anyway for rate limits, IP tracking, refresh tokens, logging, or detection of suspicious sessions. You may end up with a more complex hybrid than expected.

When you should think twice (or avoid JWTs)

Based on these tradeoffs, JWTs are often a poor fit if your system has any of the following qualities:

  • You need immediate revocation or fine grained access control such as instant logout or rapid role updates.

  • You carry sensitive user data such as personal information or secrets unless you encrypt the token first, which increases complexity.

  • Your application is small or monolithic and does not require cross domain identity or microservice level scalability. A traditional server side session system is often easier.

  • You cannot guarantee secure storage and transport such as full HTTPS, HttpOnly cookies, and protection against XSS.

  • You support low bandwidth clients such as mobile or IoT devices, or you operate under tight latency and bandwidth constraints.

See also  Designing Systems That Scale Under Variable Load

In short, JWTs make sense when you need scalable, distributed authentication. They are often unnecessary for simpler web applications and risky if used without care.

How to use JWT responsibly (if you choose them)

If you decide to adopt JWT, treat them carefully. Recommended practices include:

  • Sign tokens with a strong algorithm such as RS256 or ES256.

  • Set a reasonable expiration time and require refresh tokens for longer sessions. Short lived access tokens limit the damage if a token leaks.

  • Do not store sensitive data in the payload unless you encrypt the token using JWE instead of JWS.

  • Store tokens in secure and HttpOnly cookies rather than localStorage to limit XSS exposure.

  • If you need revocation or dynamic permissions, maintain a denylist or store session metadata on the server. This removes pure statelessness, but improves security.

These precautions add complexity, although skipping them significantly increases risk.

Example: When JWT made sense, and when it backfired

Consider a company building a microservices backend for a mobile app, a web front end, and several third party APIs.

Using JWT made sense for them. After login, the mobile app received a token. Each microservice verified it independently. No central session storage was required. Scaling was straightforward as load increased.

Later they added an administrative privilege system. One admin credential leaked. Because tokens were valid until expiration, the attacker had hours or days of unrestricted access. The team eventually added a denylist service, and at that point they needed server side state after all.

In a separate case, an internal browser based tool used by employees moved to stateless JWTs without considering XSS. Tokens were stored in localStorage. A malicious browser extension extracted the token and compromised the internal API.

See also  How to Design Fault-Tolerant APIs for Distributed Systems

Both teams gained convenience at first, then discovered deeper long term issues.

FAQ

Is JWT always more scalable than server side sessions?
Not always. If your system still requires state for revocation, rate limits, or refresh tokens, complexity may equal or exceed a session based approach.

Are JWTs safe if they only hold non sensitive data such as username and role?
They are safer, although you must still protect the token during transport and storage. Treat the token like a password. Once it leaks, it provides access until it expires.

Should I use JWT with refresh tokens and short lived access tokens?
Yes, this is often a balanced compromise. Short lived access tokens reduce the exposure window. Opaque refresh tokens or server side storage can manage long term sessions.

Should user permissions or roles be embedded in the JWT payload?
You can do this, although permission changes do not take effect until the token is replaced or invalidated. This delay is a design drawback of storing dynamic data in a static token.

Honest Takeaway

JWTs are a sharp tool. Used correctly in distributed systems, microservices, mobile backends, or cross domain APIs, they can simplify scaling and reduce the need for central session storage. That strength carries real responsibility.

If you treat JWTs casually and skip revocation systems, secure storage, and proper expiration, they quickly become security liabilities. For many small or mid sized applications, traditional session cookies or opaque tokens still offer cleaner and safer designs.

The core idea is simple. Use JWTs when their strengths match your architecture and constraints. Use them carefully. If you apply JWTs everywhere without a clear reason, you will eventually regret it.

steve_gickling
CTO at  | Website

A seasoned technology executive with a proven record of developing and executing innovative strategies to scale high-growth SaaS platforms and enterprise solutions. As a hands-on CTO and systems architect, he combines technical excellence with visionary leadership to drive organizational success.

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.