Skip to main content
Resources Security 9 min read

API Authentication: JWT vs Session Tokens vs API Keys

JWT tokens can't be revoked. Session tokens require state. API keys live too long. Understanding authentication trade-offs between security, scalability, and operational complexity.

A developer misconfigures their API authentication and ships JWT tokens with a one-year expiration. Three months later, an employee leaves. The company can’t revoke their access without maintaining a denylist—which defeats the entire point of stateless tokens.

This scenario plays out constantly because teams pick authentication mechanisms based on blog posts rather than understanding the trade-offs. Session tokens, JWTs, and API keys all authenticate requests, but they make different assumptions about trust, state, and revocation.

The Authentication Problem

You need to verify that incoming requests are authorized to perform actions on behalf of a specific user or service.

This breaks down into:

  • Authentication: Who is making this request?
  • Authorization: What are they allowed to do?
  • Accountability: Can we audit who did what?

Different authentication mechanisms handle these concerns with different trade-offs.

Session Tokens: The Traditional Approach

Session-based authentication creates a session when the user logs in, stores session data server-side, and gives the client an opaque session identifier (usually a cookie). Each request includes the session ID, and the server looks up the session to determine who the user is.

How session tokens work:

  1. User sends credentials (username/password)
  2. Server validates credentials, creates session record in database/Redis
  3. Server sends session ID to client (typically as HttpOnly cookie)
  4. Client includes session ID on subsequent requests
  5. Server looks up session data, validates, proceeds with request

What session tokens do well:

  • Immediate revocation. Delete the session record, and the token is immediately invalid. No waiting for expiration.
  • Server-side state control. All session data (permissions, user info) stays server-side. The client only gets an opaque ID.
  • Familiar model. Most web frameworks have built-in session support. Developers understand the pattern.
  • Granular control. Track last access time, session metadata, device info—anything you want in the session record.

Session token trade-offs:

  • Stateful architecture. Every request requires a database or cache lookup to validate the session. This couples your API to state storage.
  • Scaling complexity. Sessions must be shared across API servers. You need Redis, Memcached, or sticky sessions (which have their own issues).
  • Cross-domain challenges. Cookies are domain-bound. APIs serving multiple domains or mobile apps need additional mechanisms.
  • CSRF vulnerability. Cookie-based sessions are vulnerable to CSRF unless properly protected with tokens.

Best for: Monolithic web applications where the frontend and API share a domain, and you control both. Works well when you need real-time session management (admin logging out users, forcing re-authentication).

JWT (JSON Web Tokens): The Stateless Alternative

JWT packages authentication information into a signed JSON payload. The server signs the token with a secret, and clients send it with each request. The server validates the signature without needing to look up session data.

How JWT works:

  1. User sends credentials
  2. Server validates, creates JWT containing user ID, roles, expiration
  3. Server signs JWT with secret key (HS256) or private key (RS256)
  4. Client receives JWT, stores it (localStorage, sessionStorage, cookie)
  5. Client sends JWT in Authorization header: Bearer <token>
  6. Server validates signature and expiration, extracts claims, proceeds

What JWT does well:

  • Stateless. No server-side session storage required. API servers just validate signatures—no database lookup.
  • Scalable by default. Any server with the signing key can validate any token. No shared state needed.
  • Cross-domain friendly. JWTs in Authorization headers work across domains, subdomains, and mobile apps without cookie complications.
  • Contains claims. Include user ID, roles, permissions directly in the token. No database hit to know who the user is.
  • Widely supported. Libraries exist for every language. Standard format (RFC 7519) means interoperability.

JWT trade-offs:

  • Revocation is hard. Once issued, a JWT is valid until expiration. Revoking a JWT requires maintaining a denylist, which reintroduces state.
  • Token size. JWTs are larger than session IDs. Each request carries the full payload. This adds overhead, especially with many claims.
  • Secret management. Compromised signing keys invalidate your entire authentication system. Rotation is complex.
  • Sensitive data exposure. JWT payloads are base64-encoded, not encrypted. Anyone with the token can read claims. Don’t put secrets in JWTs.
  • Expiration trade-off. Short expiration is more secure but annoying (frequent re-authentication). Long expiration reduces friction but increases risk window.

Common JWT mistakes we’ve seen:

  • Storing sensitive data in the payload (it’s readable to anyone with the token)
  • Using weak secrets with HS256 (brute-forceable)
  • Not validating the alg field (algorithm confusion attacks)
  • Setting excessively long expiration times (defeats the stateless security model)

Best for: Stateless APIs, microservices architectures, mobile apps, and cross-domain scenarios. Works well when you need horizontal scaling without session storage dependencies.

API Keys: The Service Authentication Pattern

API keys are long-lived credentials used primarily for service-to-service authentication or developer API access. A key is generated, associated with a user or service, and included in requests (usually as a header or query parameter).

How API keys work:

  1. User/service generates API key through your platform
  2. Key is stored (hashed) server-side, associated with account/permissions
  3. Client includes key in requests: X-API-Key: <key> or Authorization: ApiKey <key>
  4. Server validates key against database, checks permissions, proceeds

What API keys do well:

  • Simple for developers. No authentication flow, no token refresh. Just include the key.
  • Long-lived by default. Suitable for scripts, CI/CD, integrations where interactive login isn’t feasible.
  • Easy to scope. Generate different keys with different permissions (read-only key, admin key, etc.).
  • Easy to revoke. Delete the key record, and it stops working immediately.
  • Audit trail. Track which key made which requests for accountability.

API key trade-offs:

  • Not suitable for users. API keys don’t represent individual users well—they represent applications or services.
  • Exposure risk. Long-lived keys in config files, environment variables, or code repos are common. Rotation is rare.
  • Limited context. Keys don’t carry information about the request context (like JWT claims). Every validation requires database lookup.
  • Transmission security. Keys in query parameters can leak through logs, browser history, referrer headers.

API key best practices:

  • Always use HTTPS (keys in plaintext over HTTP is catastrophic)
  • Store hashed, not plaintext (treat like passwords)
  • Support key rotation without breaking clients (allow multiple active keys)
  • Never put keys in URLs (headers only)
  • Implement rate limiting per key
  • Allow scoping keys to specific permissions/resources

Best for: Service-to-service authentication, developer API access, webhooks, CI/CD integrations, and scenarios where interactive login isn’t practical.

Authentication Methods Compared

AspectSession TokensJWTAPI Keys
StateStatefulStatelessStateful
RevocationImmediateDifficultImmediate
ScalingRequires shared storageTrivialRequires database lookup
Token sizeSmallLargeMedium
Use caseUser sessionsStateless user authService auth
ExpirationServer-controlledBaked into tokenLong-lived
Cross-domainChallengingEasyEasy
Mobile appsAwkwardNatural fitNatural fit

Hybrid Approaches

Real systems often combine these approaches:

JWT + Refresh Tokens:

  • Short-lived JWT (15 minutes) for API requests
  • Long-lived refresh token (stored server-side) to issue new JWTs
  • Balances stateless benefits with revocation capability
  • Common in OAuth 2.0 implementations

Session + JWT:

  • Create session on login (server-side)
  • Issue JWT representing the session
  • Validate JWT signature (fast) + check session still exists (secure)
  • Faster than pure session lookup, more control than pure JWT

API Keys + JWT:

  • API key authenticates the service/developer
  • Service exchanges API key for short-lived JWT
  • JWT used for actual requests
  • Combines long-lived service credentials with token expiration

Universal Security Requirements

Regardless of which authentication method you choose:

Use HTTPS everywhere. Authentication over HTTP is worthless. Credentials and tokens are transmitted in plaintext.

Implement rate limiting. Prevent brute force attacks on authentication endpoints.

Hash stored credentials. Session IDs and API keys should be hashed before storage (use bcrypt, argon2, or similar).

Monitor for anomalies. Unusual patterns (new IP, new device, unusual hours) should trigger additional verification.

Implement proper logging. Audit who accessed what, when. But don’t log the credentials themselves.

Defense in depth. Authentication is one layer. Add authorization checks, input validation, and monitoring.

Which Authentication Method to Choose

Use session tokens if:

  • You have a monolithic web application
  • Frontend and API share a domain
  • You need immediate session revocation (compliance, high security)
  • You’re okay with stateful architecture
  • Most users access via browser

Use JWT if:

  • You’re building stateless microservices
  • You need to scale horizontally without shared session storage
  • Cross-domain requests are common
  • You’re building mobile or SPA applications
  • You can accept delayed revocation or implement refresh token patterns

Use API keys if:

  • You’re authenticating services, not users
  • You’re building a developer-facing API platform
  • Interactive login doesn’t make sense for your use case
  • Long-lived credentials are acceptable
  • You need simple authentication for CI/CD, scripts, or integrations

Use hybrid approaches if:

  • You need JWT’s statelessness but also need revocation (JWT + refresh tokens)
  • You want performance of JWT with security of session validation (JWT + session verification)
  • You need different auth for different clients (API keys for services, JWT for users)

What We Actually Use

For internal APIs accessed by our frontends: JWT with refresh tokens. The stateless scaling and cross-domain support outweigh the revocation complexity. Short-lived JWTs (15 minutes) with refresh tokens stored in HttpOnly cookies give us security with reasonable UX.

For service-to-service authentication: API keys. Services don’t log in interactively. A scoped, long-lived key that can be rotated without downtime is the right tool.

For systems with strict compliance requirements or admin panels needing instant logout: Sessions. The operational overhead of Redis is worth the control.

We don’t have a single answer because different contexts have different requirements. The key is understanding the trade-offs and matching them to your constraints.

Implementation Checklist

Regardless of which method you choose:

  • Use HTTPS for all authentication-related traffic
  • Store secrets/keys/session IDs hashed, never plaintext
  • Implement rate limiting on authentication endpoints
  • Set appropriate expiration times (short for JWTs, timeout for sessions)
  • Use HttpOnly, Secure, SameSite cookies if using cookie-based auth
  • Validate all inputs and handle errors securely
  • Log authentication events (but not credentials)
  • Support MFA where it makes sense
  • Plan for credential rotation
  • Monitor for unusual authentication patterns

Authentication is fundamental to API security. There’s no one-size-fits-all answer, but understanding the trade-offs between session tokens, JWT, and API keys helps you make the right choice for your system.

Have a Project
In Mind?

Let's discuss how we can help you build reliable, scalable systems.