If you build apps, you’ll deal with login and security sooner or later. One of the most common ways to handle login in modern APIs is JWT (JSON Web Token).

In this post, you’ll learn what a JWT is, how it works step-by-step, what’s inside it, and how to use it safely.

Watch my full video explanation here:

Why JWT matters (some real numbers)

APIs run the internet now, and attackers know it.

  • Cloudflare found that successful API requests made up 57% of dynamic Internet traffic on its network (based on data observed Oct 2022–Aug 2023).
  • Akamai reported 108 billion API attacks from January 2023 to June 2024.
  • Akamai also observed 311 billion web app + API attacks in 2024, a 33% year-over-year increase.
  • In a 2024 Salt Security report survey, 95% of respondents said they experienced API security problems.

So yes—authentication is not a “later” problem. JWT is popular because it’s fast, works well with APIs, and scales nicely.

What is a JWT token?

A JWT is a compact string that carries “claims” (information) in a way that can be verified because it’s digitally signed. The official definition is in RFC 7519.

Most JWTs you see in real projects are signed tokens (JWS). They help the server confirm:

  • this token was created by us
  • it wasn’t changed in the middle
  • it hasn’t expired

Important detail: JWT is not automatically encrypted. Most JWT payloads are only Base64URL encoded, which means anyone who has the token can decode and read the payload. That’s why you should never store sensitive data (passwords, OTPs, card info, etc.) inside it.

JWT format (the 3 parts)

A JWT usually looks like this:

xxxxx.yyyyy.zzzzz

Those three parts are:

  1. Header
    Tells which algorithm is used for signing (example: RS256, HS256)
  2. Payload
    The data (claims). Example: user id, role, expiry time.
  3. Signature
    This is what makes JWT trustworthy. It’s created using the header + payload + a secret key (or private key).
    If payload changes, signature verification fails.

JWT is “self-contained”: it carries the info + proof it wasn’t tampered with.

How JWT authentication works (step by step)

Here’s the most common real-world flow:

Step 1: User logs in

User sends username/password to your server.

Step 2: Server verifies credentials

If valid, the server creates a JWT (usually an access token).

Step 3: Server sends JWT to client

Client stores it (more on safe storage later).

Step 4: Client calls your API with the token

Client sends:

  • Authorization: Bearer <JWT>

Step 5: Server verifies the token

Server checks:

  • signature is valid
  • token is not expired (exp)
  • token was issued by the right system (iss)
  • token is meant for this API (aud)

Only after that, the API returns protected data.

OWASP also recommends validating tokens carefully to avoid common JWT mistakes.

Common JWT claims you should know

Here are the claims you’ll see a lot:

  • exp (Expiry time): token is invalid after this
  • iat (Issued at): when token was created
  • iss (Issuer): who created this token
  • aud (Audience): who this token is meant for
  • sub (Subject): usually the user id
  • jti (JWT ID): a unique id (useful for preventing replay or tracking)

JWT vs Session cookies (simple comparison)

JWT is often called “stateless auth” because the server doesn’t need to store session data in memory/database for every user session.

  • Session-based auth: server stores session, client stores session id
  • JWT-based auth: client stores token, server verifies token signature

JWT can be great for:

  • mobile apps
  • SPAs (React/Angular/Vue)
  • microservices
  • distributed systems

But it’s not “always better”. It’s just a different tradeoff.

Access token vs Refresh token (very important)

Many people mix these up.

Access Token

  • short-lived (example: 5–15 minutes)
  • sent with every request
  • used to access APIs

Refresh Token

  • longer-lived (example: days/weeks)
  • used only to get a new access token
  • should be stored extra carefully

This setup reduces risk because even if an access token leaks, it expires quickly.

JWT security best practices (don’t skip this)

JWT is safe only if you implement it safely. The IETF published best-current-practices guidance in RFC 8725.

Here are the practical rules that save you from trouble:

1) Don’t put sensitive data in the payload

People can decode JWT payload easily. Signed ≠ encrypted.

Good payload: userId, role, permissions, token version
Bad payload: passwords, OTP, email verification codes, personal secrets

2) Keep access tokens short-lived

Short expiry limits damage if a token leaks.

3) Always validate signature + claims on the server

Never “trust” claims just because they exist. Validate:

  • signature algorithm
  • exp
  • iss
  • aud

This is a core point in JWT best-practices docs.

4) Never accept alg: none

Some old libraries used to accept tokens with alg=none, which is dangerous. OWASP calls this out.

5) Prefer strong algorithms and good key management

  • HS256 uses a shared secret (same key signs and verifies)
  • RS256 uses private/public key pair (better for distributed systems)

(There’s no single perfect answer, but don’t use weak keys.)

6) Use HTTPS everywhere

JWT must not travel over HTTP. OWASP recommends HTTPS for REST APIs to protect credentials/tokens in transit.

7) Store tokens safely (this is where most apps fail)

Best option for many web apps: Secure, HttpOnly cookies (reduces XSS token theft)
But if you use cookies, also think about CSRF protection (SameSite + CSRF token patterns).

If you store JWT in localStorage, it’s more exposed to XSS. (Not always wrong, but it increases risk.)

“Logout” with JWT (how it really works)

Because JWT is stateless, you can’t magically “delete it from the server” unless you design for it.

Common solutions:

  • Use short-lived access tokens + refresh tokens
  • Maintain a refresh token allowlist (and revoke refresh tokens on logout)
  • Use token versioning (like tokenVersion) stored on user record
  • For high-security apps: keep a blocklist using jti (but this reintroduces state)

Quick JWT checklist (copy/paste)

Before deploying JWT auth, check this:

  • Access token expires fast (5–15 min)
  • Refresh token is protected and revocable
  • Server verifies signature + exp + iss + aud
  • No sensitive data in payload
  • HTTPS enforced
  • alg=none rejected
  • Keys are rotated / manageable (especially if using RS256/JWKS)
  • Storage plan is safe (cookies + CSRF, or other controlled approach)

Leave a Reply

Your email address will not be published. Required fields are marked *