JWTs - Use Responsibly
Why some black hooded, Guy Fawkes mask wearing, aggressively typing dude in a dark room wants you to use JWTs for authorization
Hello again folks! Daniel here with another digest 💌
Let’s talk JWTs.
JWTs (JSON Web Tokens) are super popular. And with good reason! They're small, URL-safe, and capable of enabling stateless verification of user identity. But it’s not all roses.
As popular as they are, they are often heavily misused by developers as an authorization solution, which makes them form extremely useful tools into a potential security vulnerability. It’s not that JWTs don’t have a place in the authorization process- but it’s important they play the right one.
Oh, before I forget - Gabriel and Thomas are visiting Identiverse in Vegas soon, and are hosting a happy hour event there. If you’re there, sign up and continue the conversation there!
Now, Before we go any further, let’s talk about what JWTs actually are. Here’s a quick refresher -
What is JWT?
A JWT is a compact, URL-safe token used to represent claims between two parties. It consists of three parts:
Header: Contains metadata about the token type and cryptographic algorithms used.
Payload: Stores data or claims about the user or other entities. Claims can be predefined or custom attributes relevant to the application.
Signature: Ensures the token’s integrity and authenticity by encoding the header and payload with a secret and applying a cryptographic algorithm.
JWTs are primarily used in authentication to verify user identity without needing to query a database.
Now, you may ask yourself (If you care about this stuff as much as I do. But if you weren't you wouldn’t be reading this) What makes JWTs so popular?
Well, here’s your answer -
Why are JWTs so popular?
Three main reasons make JWTs as popular for authentication as they are: their use of JSON, decentralized (web-based) architecture, and token-based security (Get it? It’s in the name!)
JSON: The Internet and the way applications communicate with each other are based on a JSON data structure (And memes). Every JWT is essentially a JSON structure containing user information. There are, of course, many uses for JWTs. They can be used as API declarations, ID tokens, and access tokens, but their use as access tokens is the most popular.
Decentralized Architecture: JWTs support decentralized verification, enabling efficient connections between identity providers, authentication providers, and applications.
Token-Based Security: Users can verify JWTs without depending on the entity that created them. Don’t get me wrong - you still need some information from the JWT provider, but you don't need to call them to verify every JWT.
OAuth
JWTs are also popular because of the OAuth standard, which is THE standard for authentication. Brilliantly enough, OAuth stands for “Open Authorization” while being an authentication standard.
The basics of OAuth involve using multiple types of tokens, but the main ones are ID tokens and access tokens.
There are two ways to verify tokens: The first is to call the token issuer and ask, "Is this token actually valid?". Now, the second, which is more popular (due to its decentralized approach), is to look at the token itself and understand if it is valid and verifiable. This approach is possible thanks to the structure of JWT tokens -
We mentioned that a JWTs consist of three parts: a Header, a Payload, and a Signature.
The signature of the JWT allows us to verify this token by using JWKs (JSON Web Keys).
This means we can verify the token regardless of whether the issuer is available, allowing us to validate the tokens themselves even if we’re offline. By validating the tokens, we can have a very secure decentralized way to create an OAuth architecture based solely on tokens.
Ok, so if JWTs are so great, what should JWTs be used for?
What Should JWTs Be Used For?
Basically, the answer is verifying identities. Most developers rely on their authentication provider’s SDK to handle verification. (Or maybe you’ve built your own authentication solution lately—it might be 2006, and I missed it; it’s been long since I’ve been outside.) What you’ll end up getting from the JWT is the identity itself. That’s great, as JWTs are the best source for a user profile that is also verifiable. So you might not need to actually verify the JWT yourself, but you can and should use it as the source of truth for user identity.
Apart from that, you can use JWTs to extend the functionality of your authentication provider. As the JWT is self-verifiable, you can take it and make it useful in other services without involving your authentication service.
Bottom line - JWTs should be used for verification and as a source of truth for user identity and user profile.
What JWTs Aren’t
Once a user is authenticated, authorization determines what they can do. Misusing JWTs for this can lead to static, outdated permissions, and security issues.
JWTs have a payload that includes an identifiable user ID, and developers often start stuffing more data into this payload. They fill them with everything from attributes and
To keep things “““simple”””, many developers use attributes in the JWT and pair them with imperative code in the application. This often results in a statement like “If the JWT role equals something, allow/deny something”.
But Here’s the Catch
Using JWTs in this way creates two major problems:
JWTs are Static: JWTs are too static for dynamic roles and permissions. They can't easily adapt to changes, such as revoking a user's role before the token expires.
JWTs are Not Fine-Grained: JWTs have limits on the amount of data they can store, making them unsuitable for detailed access control models like ABAC or ReBAC.
Here’s more about that -
JWTs are Static
Once issued, a JWT stays the same until it expires. Imagine Role-Based Access Control (RBAC), where you decide what a user can do based on their role. JWTs only store the user and their role, but they don't update if the role changes before the token expires.
For example, if an admin is downgraded to a standard user, the JWT doesn't know about the change until it expires. This makes your authorization layer static and potentially insecure.
JWTs are not Fine-Grained
JWTs store basic user info, but they can't handle detailed access control models like Attribute-Based Access Control (ABAC) or Relationship-Based Access Control (ReBAC). There’s a limit to how much data you can cram into a JWT. If you need to grant access to thousands of files, your JWT will become ridiculously large and unwieldy, like this 20,057-character JWT that grants a user access to 1000 files. We didn’t even include the full file path.
TL;DR (If you just scrolled down here)
(Please don’t, I take it personally)
JWTs are powerful for authentication but unsuitable for authorization, and misusing them can compromise security and complicate management. Use JWTs to verify identities and rely on specialized tools for managing permissions. Rethink your authorization strategies to build secure, maintainable applications.
Thanks for sticking with me! As always, I invite you to join our Slack Community for more discussions, and don’t forget to subscribe to our Substack ❤️
Stay awesome 🌈
Daniel
The JWT can hold identity data used by an authorization engine (ABAC). It could also hold context attributes that are used to determine authorization.