How API Authentication Works — API Keys, OAuth, JWT, and Sessions

How API Authentication Works — API Keys, OAuth, JWT, and Sessions

2026-03-24

Every API needs to answer two questions: who is making this request? (authentication) and are they allowed to do this? (authorization). Authentication proves identity. Authorization checks permissions. They are separate concerns, but authentication always comes first.

There are four common approaches, each with different tradeoffs between simplicity, security, and scalability.

API Keys — Simple, Limited

An API key is a long random string that identifies the caller. The client sends it in a header or query parameter with every request:

GET /api/data HTTP/1.1
Authorization: Bearer sk_live_abc123def456...

The server looks up the key in a database, finds which account it belongs to, and checks permissions.

Advantages:

  • Simplest to implement — generate a random string, store its hash
  • Easy for developers to use (copy-paste into config)
  • Good for server-to-server communication where there's no user interaction

Limitations:

  • No expiration by default — if leaked, it works until manually revoked
  • Identifies the application, not the user (you can't tell which human made the request)
  • No standard for scoping permissions (each API invents its own scheme)
  • Must be transmitted over TLS — anyone who intercepts the key has full access

API keys are appropriate for internal services, developer tools, and third-party integrations where a human user isn't directly involved.

Session-Based Authentication — Server-Side State

Traditional web authentication: the user logs in with a username and password, the server creates a session, stores it in a database or Redis, and sends back a session ID in a cookie.

POST /login
{ "email": "[email protected]", "password": "..." }

→ Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Strict

Every subsequent request includes the cookie automatically. The server looks up the session ID, finds the user, and processes the request.

Advantages:

  • Server controls everything — sessions can be revoked instantly
  • HttpOnly cookies prevent JavaScript access (XSS protection)
  • SameSite attribute prevents cross-site request forgery (CSRF)
  • Well-understood, battle-tested pattern

Limitations:

  • Server must store sessions — requires shared storage (Redis) in a distributed system
  • Doesn't scale easily — every request requires a session lookup
  • Cookies are browser-specific — mobile apps and APIs typically prefer tokens
  • Cross-domain requests are complex (CORS + cookie policies)

Session-based auth is ideal for traditional web applications where the server and client share the same domain.

JWT — Stateless Tokens

A JSON Web Token (JWT) is a signed, self-contained token that carries claims about the user. The server doesn't need to store anything — the token itself contains the identity and permissions.

A JWT has three parts, base64-encoded and separated by dots:

header.payload.signature

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxMTMyMTYwMH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header: algorithm and token type ({"alg": "HS256", "typ": "JWT"}). Payload: claims — user ID, role, expiration time ({"sub": "42", "role": "admin", "exp": 1711321600}). Signature: HMAC or RSA signature over the header and payload, proving the token wasn't tampered with.

The server verifies the signature using a secret key (HMAC) or public key (RSA/ECDSA). If the signature is valid and the token hasn't expired, the claims are trusted. No database lookup needed.

Advantages:

  • Stateless — the server doesn't store tokens, so it scales without shared storage
  • Self-contained — the token carries identity and permissions
  • Cross-domain — sent in the Authorization header, works across any origin
  • Works for APIs, mobile apps, and microservices

Limitations:

  • Cannot be revoked before expiration (unless you maintain a blocklist, which defeats the stateless benefit)
  • Payload is readable by anyone (base64, not encrypted) — don't put secrets in it
  • Larger than session IDs (hundreds of bytes vs ~32 bytes)
  • Short expiration times require refresh token flows

OAuth 2.0 — Delegated Authorization

OAuth 2.0 is not authentication — it's authorization delegation. It lets a user grant a third-party application limited access to their resources on another service, without sharing their password.

Example: "Sign in with Google" on a third-party app. You don't give the app your Google password. Instead, Google authenticates you and gives the app a token with limited permissions.

Authorization Code Flow

The most secure OAuth flow, used by web applications:

OAuth 2.0 authorization code flow

User App Auth Server

1 click "Sign in"

2 redirect to auth server

3 user logs in + grants permission

4 redirect + auth code

5 exchange code + secret

6 access token + refresh token

7 app uses access token to call APIs Authorization: Bearer eyJ...

  1. User clicks "Sign in with Google" on the app
  2. App redirects the user to Google's authorization server
  3. User logs into Google and grants the app permission (e.g., "read your email")
  4. Google redirects back to the app with an authorization code
  5. App's backend exchanges the code + its client secret for tokens (server-to-server, not visible to the user)
  6. Google returns an access token (short-lived) and a refresh token (long-lived)
  7. App uses the access token to make API calls on behalf of the user

The authorization code is single-use and short-lived. The client secret never leaves the server. The access token expires quickly (minutes to hours). The refresh token obtains new access tokens without re-prompting the user.

Client Credentials Flow

For server-to-server communication (no user involved), the app authenticates directly with its client ID and secret:

POST /oauth/token
grant_type=client_credentials
client_id=xxx
client_secret=yyy

Simpler than authorization code, but only works when there's no user context.

Which Approach to Use

ApproachBest forStateful?Revocable?
API keyServer-to-server, developer toolsYes (key lookup)Yes
SessionTraditional web apps, same-domainYes (session store)Yes (instant)
JWTAPIs, mobile, microservicesNo (stateless)No (until expiry)
OAuth 2.0Third-party access, "Sign in with X"Depends on token typeYes (revoke grant)

In practice, many systems combine approaches. OAuth issues a JWT as the access token. The JWT is verified statelessly for most requests. A blocklist catches revoked tokens that haven't expired yet.

Next Steps