What Is a JWT? JSON Web Tokens Explained Simply
Supabase, Firebase, Auth0, and Clerk all hand your app JWTs. What a JSON Web Token is, its three parts, why anyone can read it but nobody can forge it, how apps use it for login, and the mistakes AI-generated code makes with tokens.
If your app uses Supabase, Firebase, Auth0, Clerk, or most other login services, it's handling JWTs — long strings starting with eyJ that appear in headers, cookies, and local storage. Here's what they are and how to handle them safely.
The short version
A JWT (JSON Web Token, often pronounced "jot") is a small, signed piece of data that says something like "this is user 42, and it's valid until 3pm." The server that issued it signs it with a secret, so anyone can check it's genuine, and nobody can change it without the signature breaking.
It's like a festival wristband: it proves you paid, the staff can check it at a glance, and a fake is easy to spot.
The three parts
A JWT looks like this (shortened):
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiIsImV4cCI6MTc5MDAwMDAwMH0.Xk9f2…
└──── header ────────┘ └────────── payload ───────────────────┘ └ signature ┘
Three sections separated by dots:
- Header — which signing method was used.
- Payload — the actual information, called claims.
- Signature — proof the first two parts haven't been altered.
The header and payload are just JSON, encoded (not encrypted) into URL-safe text. Decoded, the payload might be:
{
"sub": "42",
"email": "[email protected]",
"role": "authenticated",
"exp": 1790000000
}
Common claims: sub (subject — the user ID), exp (expiry time), iat (issued at), iss (issuer). (What Is JSON?.)
Anyone can read it. Nobody can forge it.
This is the key thing to understand:
- The payload is not secret. Anyone who has the token can decode it — paste one into a JWT debugger site and you'll see everything. Never put passwords, secrets, or sensitive personal data in a JWT.
- The signature makes it tamper-proof. If someone edits the payload — changing
"sub": "42"to"sub": "1"— the signature no longer matches, and a server that checks it will reject the token.
So a JWT proves who issued it and that it hasn't changed. It doesn't hide anything.
How apps use JWTs for login
- You log in. The auth service checks your password and issues a JWT.
- Your app stores it — ideally in an
HttpOnlycookie. (What Is a Cookie?.) - With each request, the token is sent along, often in a header:
Authorization: Bearer eyJhbGciOi… - The server verifies the signature and expiry, then trusts the claims: "this is user 42."
The appeal: the server doesn't need to look anything up in a database to know who you are. That makes JWTs popular for APIs and for services like Supabase, where the database itself reads the JWT to enforce row-level security. (Supabase Row-Level Security Explained.)
Access tokens and refresh tokens
Because a JWT is valid until it expires — and generally can't be cancelled early — well-designed systems keep them short-lived, often an hour or less. To avoid logging you out every hour, they pair it with a refresh token: a longer-lived credential used only to get a fresh JWT.
If you use a login service or library, it handles this rotation for you. That's one of the best reasons to use one. (How to Add Login to an AI-Built App.)
Mistakes AI-generated code makes with JWTs
- Decoding without verifying. Reading the payload with a decode function and trusting it, without checking the signature. Anyone can then create a token saying they're an admin. Always use your library's verify function on the server.
- Trusting the token in the browser. Checks like
if (token.role === "admin")in front-end code only change what's displayed. The server must make the real decision. (Authentication vs Authorization.) - Weak or leaked signing secrets. A short secret like
secret123can be guessed; a secret in front-end code or committed to Git lets anyone sign tokens. Treat it like a password. (How to Keep API Keys Out of an AI-Built App.) - No expiry, or very long expiry. A stolen token that never expires is a permanent key.
- Storing tokens in local storage where any injected script can read them. (What Is XSS?.)
- Putting sensitive data in the payload, forgetting anyone can read it.
- Building custom JWT auth when a service or library would do. Let the experts handle token issuance and rotation.
Supabase's "anon" and "service role" keys
A special case worth knowing: Supabase's anon key and service_role key are themselves JWTs. The anon key is designed to be public, as long as row-level security is on. The service_role key bypasses all security rules and must never reach the browser. If you see it in front-end code, move it to the server and rotate it.
EasySpawn gives your app a real server-side environment where signing secrets and service keys live in environment variables — never in the code your users download. See how it works for AI-built apps or join the waitlist.
Related: What Is a Cookie? · "Sign in with Google" Explained · Password Hashing Explained
Keep reading
GDPR Basics for App Builders: What a Small App Actually Needs
If anyone in the EU or UK uses your app, GDPR probably applies. What personal data is, the principles in plain English, lawful bases, the rights users have (access, deletion), what to do about third-party services and data breaches, and a practical checklist for a small app. Not legal advice.
Form Validation Explained: Client-Side, Server-Side, and Why You Need Both
Validation checks that what users type makes sense before you save it. The difference between browser-side and server-side validation, why only the server's counts for security, built-in HTML validation, sharing rules with a schema, and writing error messages people understand.