Your APIs Are Only as Secure as Your JWTs

Key Takeaways

  • JWTs are popular for access tokens due to their statelessness and ease of use, but they're often adopted hastily without understanding the security tradeoffs.

  • A common misuse: using JWTs for session management. Since JWTs can't be invalidated before expiry, this makes proper logout impossible — sessions can only "expire," not be revoked.

  • Symmetric signing (shared secret) requires careful handling — sufficient entropy, secure key rotation, and never embedding the secret in client-side code like SPAs or mobile apps, where it can be extracted.

  • Misconfigured JWTs (weak keys, allowing the "none" algorithm) can lead to Broken Object/Function Level Authorization — both listed in OWASP's API security top ten.

  • Tokens must contain sufficient scopes and claims for the API to make informed authorization decisions — not just whatever's convenient to include.

  • Bottom line: don't adopt JWTs just because they're trendy — follow established best practices and security cheat sheets rather than implementing security features from scratch.

On this page

API security has matured over the years. As an industry, we have moved from API-key-based security to token authorization. And most companies today typically leverage either OAuth or OpenID Connect standards to secure their APIs with tokens. This is a positive trend (which large API ecosystems can take even further) that helps increase the security of APIs.

Since Access tokens are short-lived, they don't share the risks of immutable API keys. They also include (or reference) all the necessary data that an API needs to perform authorization decisions. As with all security solutions, though, there are some things to look out for when securing APIs with access tokens, especially when JSON Web Tokens (JWTs) are considered.

The Popularity of JWTs

JWT has become a very popular format for access tokens, mainly thanks to the ease of use and statelessness. However, it's not the only access token format — by-reference and opaque tokens are also widely used. You can even combine formats in a pattern called the Phantom Token Approach.

JWTs can be used outside of access tokens too. A JWT is useful in many scenarios that require sharing integrity-protected data (thanks to the token's signing) or confidential data (using encrypted JWTs). For example, JWTs can authenticate applications, where an application issues a signed JWT, and the receiver can verify the app's identity by verifying the signature.

There is nothing wrong with using JWTs as access tokens, though the choice is sometimes made hastily, without proper insight. Often, developers decide to use JWTs simply because it's a trendy security feature. Or, what's worse is that some folks claim JWTs are a great way to manage sessions across backend instances without a persistence layer (thanks to the fact that all the session data is kept inside the JWT).

One should remember that JWTs were never designed for handling sessions. They're not a good fit for this for one simple reason: JWTs can't be invalidated. They are valid for as long as the expiration time of the JWT itself. This means that if you're using JWTs for session handling, your users can't log out of your application. Instead, they must wait until their session is over.

The popularity of JWTs adds to these problematic usage patterns. Since they are popular, developers don't always consider the security implications of their use. A developer will often finish a tutorial on how to issue and verify JWTs in framework X and implement it straight away in their solution. But without security forethought, hasty adoption can lead to misconfigurations or improper settings that render JWTs much less secure.

The Devil Is in the Details

As with many technologies, especially around security, the details are essential. It's simple to start using JWTs, but it's important to use them securely — this includes understanding why you're using specific settings and how to use particular aspects effectively.

jwt is one of my favorite tags on Stack Overflow, and I tend to answer and review many questions here. Frequently, I encounter people using JWTs with symmetric signing algorithms. Even though asymmetric signing is usually preferred, you should be aware of the caveats and recommendations when using symmetric signing.

For example, are you using a secret with enough entropy so that it's hard to brute-force it? Do you have a procedure in place for key rotation? If many services are verifying your JWT, they all need access to the secret. Thus, you need to be able to quickly feed them the new secret. Not to mention that the secret cannot be shared with a Single Page Application (SPA) or a mobile app as it will not be a secret anymore (anyone can access the code of your SPA and mobile app, so they can easily extract any embedded secrets).

Think about it this way — if you organized a concert, you wouldn't print tickets on a home printer, would you? Issuing tickets to a concert doesn't guarantee they won't be abused — it's how you issue and secure those tickets that protects them.

Using misconfigured JWTs or JWTs that misuse important features (such as using weak symmetric keys, or allowing the algorithm 'none' to be used for verification) can lead to Broken Object Level Authorization or Broken Function Level Authorization vulnerabilities. These vulnerabilities can expose a state where the user can access other data or endpoints that are beyond their privileges. Together with Security Misconfiguration, these vulnerabilities are all present on OWASP's list of top ten API vulnerabilities.

Proper usage of JWTs is truly an integral part of your API's security layer. This is also the case when the content of the JWT is insufficient for an API to perform an informed authorization decision. This means that tokens should be populated with proper scopes and claims depending on the requesting client, authenticated user, method of authentication used, and other factors.

Security Is Hard

It's common knowledge that security is hard. It's even harder when you implement it in a homegrown way. It's also impossible for all developers in your organization to become security experts, and thankfully, they shouldn't have to.

When considering security, as in many other areas of software development, it is good to tap into the knowledge and experience of others. For many areas of security, you can find best practices and cheat sheets. Some are even published as standards (or draft standards), like the security best practices for OAuth or the OAuth best practice for native apps. Creating secure solutions is much simpler once you follow those best practices.

When it comes to JWTs, at Curity, we have compiled a best practice article to help others avoid the common pitfalls. There is also a free online course on the same topic.

Conclusion

You should never implement new technologies just because they're hip or many people around you recommend them. This is especially true when it comes to security features. Your decisions should always be informed — you should be aware of why you want to use that particular piece of technology, and, even more importantly, how to properly integrate it.

Thankfully, there are many resources out there, as security experts are keen to share their experience so that others can create more secure and robust solutions. Don't hesitate to reach for those resources!

Sometimes adhering to security best practices is more straightforward when using the right tools. For example, if your authorization server doesn't allow unsigned JWTs, you don't have to worry about rejecting unsigned JWTs. The Curity Identity Server comes with a feature-rich Token Service to facilitate working with JWTs, claims, scopes, impersonation techniques, token sharing, and many more.

Related resources

Frequently Asked Questions

If JWTs can't be invalidated, is there any way to effectively "revoke" one before it expires?

Some workarounds exist, like maintaining a server-side deny-list (blocklist) of revoked token IDs that APIs check against, but this reintroduces the statefulness JWTs were meant to avoid — which is why patterns like the phantom token approach (using short-lived opaque tokens instead) are often recommended when revocation matters.

What's the practical difference between symmetric and asymmetric signing for JWTs?

Symmetric signing (like HMAC) uses one shared secret for both signing and verification, meaning every verifying service needs access to that same secret, while asymmetric signing (like RSA or ECDSA) uses a private key for signing and a public key for verification, allowing many services to verify tokens without ever holding sensitive signing material.

Why is allowing the "none" algorithm in JWT verification a security risk?

The "none" algorithm option means a token claims to have no signature at all — if a verification library isn't configured to reject this, an attacker can craft an unsigned token with arbitrary claims and have it accepted as valid, completely bypassing signature verification.

How short should a JWT access token's lifespan be to minimize risk?

There's no universal number, but shorter lifespans (often minutes, not hours or days) are generally recommended to limit the window of exposure if a token is compromised, with refresh tokens used to obtain new access tokens without requiring the user to log in again.