Authentication and JWT

6 min read

Reading Progress0%
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Tier 2 -- Communication Models
Tier 3 -- Production & API Hardening
Web Backend Fundamentals Index
Tier 1 -- Core Web & API Basics
Tier 2 -- Communication Models
Tier 3 -- Production & API Hardening

Authentication and JWT

1. What It Is

Authentication is the process of verifying that a request comes from who it claims to be. In web backends, this almost always means: a user provides credentials, the server verifies them, and then issues a token or that the client sends on every subsequent request.

(JSON Web Token) — RFC 7519 — is a compact, self-contained token format widely used for authentication. Unlike server-side sessions, a encodes user identity and claims directly in the token, signed by the server so the server can verify it without looking up anything in a database.

Why it matters: every backend that has a login page, an API with access control, or a mobile app needs authentication. JWT is the dominant stateless auth mechanism in modern APIs.


QUICK CHECK

A backend API uses JWTs for authentication. When a protected endpoint receives a request with a JWT, what does the server need to do to confirm the request is legitimate?

Choose one answer

2. How It Works in Practice

JWT Structure

A is three Base64url-encoded segments joined by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.        ← Header
eyJ1c2VySWQiOjQyLCJyb2xlIjoiYWRtaW4ifQ.      ← Payload (claims)
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c  ← Signature

Header: algorithm (e.g., HS256, RS256) and token type.

Payload (claims):

  • sub — subject (user ID)
  • iat — issued at (Unix timestamp)
  • exp — expiry
  • custom claims: role, email, tenantId, etc.

Signature: computed from header + payload using a secret key (HMAC) or private key (RSA/ECDSA). Tampering with the payload breaks the signature.

Authentication Flow

Client                          Server
  |                               |
  |-- POST /auth/login ---------->|
  |   { email, password }         | 1. Verify credentials
  |                               | 2. Issue JWT (exp: 15 min)
  |<-- 200 OK --------------------|
  |   { access_token: "eyJ..." }  |
  |                               |
  |-- GET /api/me --------------->|
  |   Authorization: Bearer eyJ...| 3. Verify signature + expiry
  |                               | 4. Extract claims from payload
  |<-- 200 OK --------------------|
  |   { id: 42, role: "admin" }   |

The server never stores the . It just re-verifies the signature on every request.

Refresh Token Pattern

Short-lived access tokens (15 min) paired with long-lived refresh tokens (7 days) stored securely:

  1. Login → server issues access_token (short TTL) + refresh_token (long TTL, stored in HttpOnly ).
  2. Client uses access_token in Authorization header.
  3. When access_token expires → client hits /auth/refresh with the refresh_token.
  4. Server issues a new access_token (and optionally rotates refresh_token).
  5. If user logs out → server invalidates the refresh_token in its database.

QUICK CHECK

A user logs into your API and receives a JWT access token that expires in 15 minutes. Twenty minutes later, the user makes a request with that token and receives a 401 Unauthorized response. Your system uses the refresh token pattern. What should the client do next to restore the user's session without requiring them to log in again?

Choose one answer

3. Common Real-World Usage

SPA + API: the frontend JavaScript app stores the access token in memory (not localStorage), attaches it to every API call in the Authorization: Bearer <token> header.

Mobile apps: tokens stored in secure platform storage (Keychain on iOS, Keystore on Android).

Microservices: each service verifies the independently without calling a central auth server — this is the main scalability benefit.

Libraries:

  • Node.js: jsonwebtoken, jose
  • Python: python-jose, PyJWT
  • Java: nimbus-jose-
  • Go: golang-jwt/jwt

QUICK CHECK

A team is building a microservices architecture where multiple services need to authenticate incoming requests. They are deciding between two approaches: (A) each service calls a central authentication server to validate every token, or (B) each service independently verifies the JWT using a shared public key. What is the primary scalability advantage of approach B?

Choose one answer

4. Trade-offs and Common Mistakes

Trade-offs: JWT vs. Server Sessions

JWTServer Session
StateStateless (no DB lookup)Server stores state
Logout/revocationHard (token valid until expiry)Easy (delete session)
ScaleEasy — any node validates independentlyRequires shared session store (Redis)
Payload sizeGrows with claimsTiny (just a session ID)
Security surfaceToken theft = impersonation until expirySession theft same risk; easier to revoke

Common Mistakes

Storing in localStorage: JavaScript-accessible, so any vulnerability can steal it. Prefer in-memory storage for access tokens; use HttpOnly cookies for refresh tokens.

Long-lived access tokens without refresh: a 30-day access token that cannot be revoked is a security nightmare. Keep access tokens short (5–30 min).

Skipping expiry validation: always check exp. Libraries do this for you if you use them correctly; don't write raw verification by hand unless you know what you're doing.

Trusting the alg header: a classic attack is sending alg: none to bypass signature verification. Always specify the algorithm explicitly server-side — never accept what the token says.

Putting sensitive data in the payload: the payload is Base64-encoded, not encrypted. Anyone with the token can decode it. Never put passwords, secrets, or sensitive PII in claims.

Not rotating refresh tokens: if a refresh token is leaked, an attacker can generate new access tokens indefinitely. Implement refresh token rotation: invalidate the old refresh token when a new one is issued.


QUICK CHECK

Your API issues JWTs with a 30-day expiry. A user's token is stolen in a data breach. What is the most significant security problem with this setup, and what is the recommended mitigation?

Choose one answer

5. Interview Angle

How to explain it

" is a signed token. The server issues it after login, and the client sends it on every request. The server verifies the signature cryptographically — no database lookup needed. The key trade-off vs. sessions is that JWTs are hard to revoke: you can't invalidate them before they expire unless you maintain a token blacklist, which kills the statelessness benefit."

Common interview questions

Q: How does work at a high level? A: Three parts — header, payload, signature — joined by dots. The server signs the header + payload with a secret or private key. On each request, the server re-verifies the signature and checks expiry. No server-side storage needed.

Q: How do you handle logout with JWTs? A: Short access token TTL (15 min) so they expire quickly. For immediate revocation: maintain a token blacklist (Redis set of revoked JTIs) or use refresh token invalidation — the access token expires soon anyway.

Q: HS256 vs. RS256 — when would you choose each? A: HS256 uses a shared secret — simpler, but every service that verifies tokens needs the secret. RS256 uses a private key to sign and a public key to verify — services only need the public key, making it better for microservices or when third parties verify tokens.

Q: Where should you store JWTs on the client? A: Access tokens in memory (not localStorage — risk). Refresh tokens in HttpOnly, Secure, SameSite=Strict cookies — inaccessible to JavaScript.

Q: What are JWT claims? A: Key-value pairs in the payload. Standard claims: sub (subject/user ID), iat (issued at), exp (expiry). Custom claims: role, tenantId, etc. Claims are signed but not encrypted.


QUICK CHECK

Your team is building a microservices architecture where multiple independent services need to verify authentication tokens, and some of those services are maintained by a third-party vendor. Which JWT signing algorithm is the better fit, and why?

Choose one answer

6. Practical Examples

Node.js: issue and verify JWTs

const jwt = require('jsonwebtoken');

const SECRET = process.env.JWT_SECRET;

// Issue on login
function issueToken(userId, role) {
  return jwt.sign(
    { sub: userId, role },
    SECRET,
    { algorithm: 'HS256', expiresIn: '15m' }
  );
}

// Middleware to verify
function authMiddleware(req, res, next) {
  const header = req.headers.authorization;
  if (!header?.startsWith('Bearer ')) return res.status(401).json({ error: 'Unauthorized' });
  const token = header.slice(7);
  try {
    const payload = jwt.verify(token, SECRET, { algorithms: ['HS256'] });
    req.user = payload;
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid or expired token' });
  }
}

Python: issue and verify

import jwt
from datetime import datetime, timezone, timedelta

SECRET = "your-secret-key"

def issue_token(user_id: int, role: str) -> str:
    payload = {
        "sub": str(user_id),
        "role": role,
        "iat": datetime.now(timezone.utc),
        "exp": datetime.now(timezone.utc) + timedelta(minutes=15),
    }
    return jwt.encode(payload, SECRET, algorithm="HS256")

def verify_token(token: str) -> dict:
    # Raises jwt.ExpiredSignatureError, jwt.InvalidTokenError on failure
    return jwt.decode(token, SECRET, algorithms=["HS256"])

Refresh token flow (pseudocode)

POST /auth/login
→ { access_token: "eyJ...15min", refresh_token: "opaque-uuid-stored-in-db" }
   └─ refresh_token goes into HttpOnly cookie

POST /auth/refresh
  Cookie: refresh_token=opaque-uuid
→ Server looks up uuid in refresh_tokens table (checks valid, not revoked, not expired)
→ Rotate: delete old uuid, create new uuid
→ { access_token: "eyJ...new-15min" }

POST /auth/logout
  Cookie: refresh_token=opaque-uuid
→ Server deletes uuid from refresh_tokens table
→ 204 No Content
QUICK CHECK

In a refresh token flow, a user's refresh token is stored as an opaque UUID in a database rather than as a self-contained signed JWT. When the user calls POST /auth/refresh, the server rotates the token — deleting the old UUID and issuing a new one. What is the primary security advantage of this rotation strategy?

Choose one answer