Skip to main content

JWT Authentication for APIs: What & Why

JWT (JSON Web Token) is a stateless authentication method where a signed token contains user identity and is validated via cryptographic signature rather than server-side session storage. Instead of your API querying a database on every request, clients send a compact, self-contained token that proves who they are. This pattern powers authentication across billions of API requests daily at companies like Google, Auth0, and Twilio.

What Is a JSON Web Token?

A JWT is a digitally signed string composed of three base64-encoded parts separated by dots: header, payload, and signature. The header declares the token type and signing algorithm (typically HS256 or RS256). The payload contains claims—structured data about the user (user ID, email, roles) and metadata (expiration, issued-at time). The signature is computed by hashing the header and payload with a secret key, ensuring tampering is immediately detectable.

Example token structure:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNjc2OTU0MDAwfQ.
1a2b3c4d_signature_hash_here

How JWT Authentication Works

When a user logs in with a username and password, your API validates the credentials (username exists, password hash matches), then creates and returns a JWT. The client stores this token (in memory, localStorage, or a cookie) and includes it in subsequent requests via the Authorization: Bearer <token> header. Your API extracts the token, verifies its signature using your secret key, decodes it, and permits the request if the signature is valid and the token is not expired. Critically, no server-side database lookup is required—the signature guarantees the token is legitimate.

JWT vs. Session-Based Authentication

AspectJWTSessions
StorageStateless (client-side)Stateful (server database)
ScalabilityHorizontal (any server can verify)Requires shared session store
Token SizeLarger (base64-encoded claims)Small (just session ID)
RevocationDifficult (token valid until expiry)Immediate (delete session)
Use CaseMobile apps, SPAs, microservicesTraditional monolithic web apps

Why Use JWT for APIs?

Stateless & Scalable: Each API server verifies tokens independently. No shared session database is needed, so you can scale horizontally without complex session replication. If you have 100 API servers, all can validate the same token instantly.

Mobile & Cross-Origin Friendly: Sessions rely on cookies, which are restricted by browsers for security. JWTs travel freely in headers, making them ideal for mobile apps and cross-origin requests.

Microservices Ready: In a microservice architecture, user identity must flow across services. JWTs embed all necessary claims, so service B trusts a token validated by service A (if they share the signing key).

Reduced Database Load: Session-based auth queries the database on every request. JWT validation is pure cryptography—no I/O, hundreds of times faster.

JWT Claims and Payload

Standard JWT claims are registered names recognized by specs (RFC 7519). Common ones:

  • sub (subject): User ID or unique identifier
  • exp (expiration): Unix timestamp when token expires
  • iat (issued at): When the token was created
  • iss (issuer): Application name or domain
  • aud (audience): Intended recipient(s) of the token

You can add custom claims (e.g., email, roles, permissions) to embed user context directly in the token.

Signature Verification: The Security Foundation

A JWT signature is computed as:

signature = HMAC_SHA256(
base64(header) + "." + base64(payload),
secret_key
)

When the token arrives at your API, you recompute this signature using the same secret key. If the computed value matches the token's signature, you know the token hasn't been tampered with. If anyone changes the payload (e.g., altering user_id) without the secret key, the signature will be invalid and the token is rejected.

Key Security Considerations

Secret Key Protection: Your signing key is the crown jewel. Store it in environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault), never in code or version control. If compromised, an attacker can forge valid tokens.

Token Expiration: JWTs should have a short lifetime (15 minutes for access tokens is typical). This limits the damage if a token is stolen. Refresh tokens (longer-lived, used only to issue new access tokens) extend user sessions securely.

HTTPS Only: Always transmit JWTs over HTTPS. Unencrypted connections expose tokens to interception.

Signature Algorithm: Prefer HS256 (HMAC with SHA-256) for shared secrets or RS256 (RSA) for public-key cryptography in microservices where one service signs and others verify.

Key Takeaways

  • JWT is a stateless, cryptographically signed token containing user claims, ideal for APIs and microservices.
  • The signature guarantees the token hasn't been altered; no database lookup needed to verify.
  • JWTs are larger than session IDs but eliminate server-side state, enabling horizontal scaling.
  • Short expiration times and secure key storage are essential to prevent token misuse.
  • Next articles will show how to implement JWT in FastAPI, refresh tokens, and combine JWTs with scopes and roles.

Frequently Asked Questions

Can a JWT be revoked before expiration?

JWTs cannot be revoked until they expire—a key limitation. If a user is locked out or changes their password, issued tokens remain valid. Common solutions are maintaining a token blacklist (database of revoked tokens, checked on each request) or issuing very short-lived access tokens (5–15 min) paired with refresh tokens.

Is JWT suitable for all authentication scenarios?

JWTs excel for APIs and microservices but are overkill for simple server-rendered websites where sessions work fine. Use JWT when you need stateless, scalable authentication across multiple services or mobile clients.

What's the difference between HS256 and RS256?

HS256 uses a shared secret (both signer and verifier have the same key); ideal when one service signs and verifies. RS256 uses RSA public-key pairs (sign with private key, verify with public key); used in OAuth2 and microservices where many services need to verify tokens signed by a central auth server.

How do I safely store a JWT on the client side?

In browsers, in-memory storage or httpOnly cookies (cannot be accessed by JavaScript) are safest; localStorage is vulnerable to XSS attacks. Mobile apps store tokens in secure storage (Keychain on iOS, Keystore on Android). Always transmit over HTTPS.

Further Reading