Guide
API
Developer Reference

API Authentication Methods: API Keys, JWT, OAuth 2.0, and HMAC

A practical guide to choosing and implementing the right API authentication strategy.

Last updated: Feb 27, 2026

API Keys

A static secret string that identifies the caller. The server validates the key against a database on each request.

Best for: Server-to-server calls, internal services, simple third-party integrations

JWT (JSON Web Token)

A signed token that contains encoded claims. The server verifies the signature cryptographically — no database lookup required.

Best for: Stateless auth, microservices, user sessions with embedded context

OAuth 2.0

A delegated authorization framework. Users grant limited access to their data without sharing credentials. Issues short-lived access tokens.

Best for: Third-party app access, "Login with Google/GitHub", user-delegated permissions

HMAC Request Signing

Each request is signed using a shared secret and HMAC. The signature covers the method, path, headers, and body — preventing tampering and replay attacks.

Best for: Webhook verification, financial APIs, high-security service-to-service calls (e.g., AWS Signature v4)

Which Method Do I Need?

Use CaseRecommended Approach
Server-to-server API calls (same trust boundary)API Key
User login — stateless session tokenJWT
"Login with Google / GitHub" — delegated authOAuth 2.0
Third-party app accessing user's dataOAuth 2.0
Webhook payload verificationHMAC Signature
High-security API with tamper-proof requests (e.g., AWS)HMAC Request Signing
Microservices passing user context without DB lookupJWT
Simple public API with rate limiting per consumerAPI Key

API Keys

An API key is a long random string — typically 128 or 256 bits of entropy — that the client includes in every request. When the server receives the request, it looks up the key in its database to identify the caller and check permissions.

API keys are opaque: they carry no information themselves. The server resolves all context (who this is, what they can do) from the database record associated with the key. This makes revocation trivial — just delete or deactivate the record — but it also means every request requires a database lookup.

Keys are typically sent in the Authorization: Bearer <key> header or a custom header like X-API-Key. Never put keys in URL query parameters — they end up in server logs, proxy caches, and browser history.

Strengths

  • • Simple to implement and use
  • • Instant revocation (delete from DB)
  • • Easy to scope per client or service
  • • Works with any HTTP client

Weaknesses

  • • DB lookup required on every request
  • • Static — no expiry unless you add it
  • • No built-in integrity protection
  • • Leaked keys are immediately usable

Use the API Key Generator to create cryptographically secure keys. For a direct comparison of API keys and JWTs, see API Key vs JWT.

JWT (JSON Web Tokens)

A JWT is a compact, self-contained token that encodes claims (key-value pairs of information) and includes a cryptographic signature. The three parts — header, payload, and signature — are Base64URL-encoded and joined with dots:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyXzEyMyJ9.signature

The signature is computed over the header and payload using either a shared secret (HMAC-SHA256 → HS256) or a private key (RSA or ECDSA → RS256/ES256). The server verifies the signature without touching a database. This is the key advantage of JWTs: stateless verification.

Common claims include sub (subject — usually user ID), exp (expiration), iat (issued at), and aud (audience). Always set exp — JWTs without expiration are long-lived tokens that can't be easily revoked.

JWTs are not encrypted by default — anyone who has the token can decode the payload. Never put sensitive secrets in JWT claims unless you use JWE (JSON Web Encryption). The signature only guarantees integrity, not confidentiality.

Revocation challenge

Because JWTs are verified without a database, revoking a specific token before it expires is hard. Common mitigations: use short expiry times (15 minutes), maintain a token blocklist, or use refresh-token rotation. Pick expiry times that match your security requirements.

Strengths

  • • Stateless — no DB lookup per request
  • • Carries user context in the token
  • • Works well in microservices
  • • Self-expiring with exp claim

Weaknesses

  • • Hard to revoke before expiry
  • • Payload visible (not encrypted)
  • • Token size grows with claims
  • • Key rotation requires coordination

Inspect a JWT in the browser with the JWT Decoder. For a side-by-side comparison with API keys, see API Key vs JWT.

OAuth 2.0

OAuth 2.0 is an authorization framework, not an authentication protocol. It lets users grant limited access to their data on one service to another service — without sharing their password. "Login with Google" is OAuth. Reading a user's GitHub repos from your app is OAuth.

The core flow (Authorization Code grant, the most common): the user is redirected to the authorization server (Google, GitHub, etc.), they approve the requested scopes, and your app receives an authorization code. Your backend exchanges the code for an access token (and optionally a refresh token). The access token is then used to call the resource server (API) on the user's behalf.

Access tokens are short-lived (often 1 hour). Refresh tokens let your app obtain new access tokens without re-prompting the user. Scopes limit what the access token can do (e.g., read:email vs repo:write).

OpenID Connect (OIDC) extends OAuth 2.0 for authentication — it adds an id_token (a JWT) that identifies the user. If you need both "who is this person" and "what can they access," OIDC is the standard.

OAuth 2.0 vs API Keys — key distinction

API keys represent the application itself. OAuth tokens represent a user's delegation to the application. If your API is called by other applications acting on behalf of users, use OAuth. If your API is called by other backend services acting on their own behalf, API keys or JWTs are usually simpler.

Strengths

  • • User doesn't share password with your app
  • • Fine-grained scopes (principle of least privilege)
  • • Short-lived access tokens
  • • Standardized — works with identity providers

Weaknesses

  • • More complex than API keys or JWTs
  • • Requires an authorization server
  • • Multiple round-trips for initial auth
  • • Overkill for simple M2M (machine-to-machine) calls

HMAC Request Signing

HMAC request signing goes further than API keys. Instead of sending the key directly, the client uses the secret key to compute an HMAC over specific request components — the HTTP method, path, headers (like Date or Content-Type), and often the request body. The resulting signature is sent in the request; the secret key is never transmitted.

The server recomputes the HMAC with the same key and compares signatures. If they match, the request is authentic and unmodified. Including a timestamp in the signed content prevents replay attacks — a signature that's more than a few minutes old is rejected.

HMAC signing is used by AWS (Signature Version 4), Stripe webhook signatures, GitHub webhook signatures, and many payment gateways. It provides a higher security bar than API keys because a captured request can't be replayed or modified. However, it is significantly more complex to implement correctly.

HMAC vs plain API keys — the security difference

With an API key, an intercepted key can be reused indefinitely. With HMAC signing, intercepting a request only gives you a single-use signature for that exact request at that timestamp. The actual secret never travels on the wire.

Strengths

  • • Secret never transmitted
  • • Tamper-evident (covers request body)
  • • Replay-attack resistant with timestamps
  • • Standard for high-security APIs

Weaknesses

  • • More complex to implement
  • • Clock synchronization required
  • • Hard to test manually
  • • Shared secret still needs secure distribution

Test HMAC signatures with the HMAC Generator. For a deeper look at HMAC, see the Hashing and HMAC guide.

Side-by-Side Comparison

AspectAPI KeyJWTOAuth 2.0HMAC Signing
Stateless?No (DB lookup)YesPartialNo (DB lookup for secret)
Carries data?NoYes (claims)Partial (scope/iss in token)No
ExpiryManual / noneBuilt-in (exp claim)Short-lived access tokenPer-request (timestamp)
RevocationEasy (delete from DB)Hard (blocklist needed)Easy (revoke refresh token)Easy (delete secret)
Replay protectionNoPartial (exp)PartialYes (timestamp in sig)
Integrity protectionNoToken only (not request)Token onlyFull request + body
Implementation complexityLowMediumHighHigh
Primary use caseM2M, simple APIsUser sessions, microservicesDelegated user accessHigh-security M2M, webhooks

Real-World Patterns

SaaS API (Stripe, GitHub, Twilio style)

Public-facing APIs typically use API keys for server-to-server calls and OAuth 2.0 for user-delegated access. Stripe uses secret API keys (sk_live_...) for backend calls, and OAuth for third-party apps to act on behalf of Stripe account holders.

Webhook endpoints use HMAC signatures to verify that payloads are genuinely from the provider. Check the Stripe-Signature or X-Hub-Signature-256 header before processing.

Microservices Architecture

Users authenticate at the edge (API gateway) and receive a short-lived JWT. The gateway forwards this JWT to internal services, which verify it locally without a database call. Each service extracts the user ID, roles, and tenant from the JWT payload.

Service-to-service calls (no user context) use API keys or mTLS. JWTs work well for propagating user identity across service boundaries without coupling services to a central auth database.

Cloud Provider APIs (AWS style)

AWS uses HMAC request signing (Signature Version 4) for every API call. The access key ID is sent in the request (not a secret), but the secret access key is used only to compute the HMAC. The signature covers the method, URL, headers, and body hash — preventing any modification or replay.

This approach provides strong guarantees for financial, infrastructure, and compliance-critical systems where API key interception would be catastrophic.

Mobile App Authentication

Mobile apps typically implement OAuth 2.0 PKCE flow: the user logs in via the authorization server (your backend or an identity provider like Auth0), receives an access token (often a JWT), and uses it for API calls. The refresh token keeps the user logged in without re-authentication.

Never embed long-lived API keys in mobile apps — they can be extracted from the binary. Short-lived tokens with refresh capability is the correct pattern.

Common Mistakes

X

Putting API keys in URLs

Query parameters appear in server logs, browser history, proxy caches, and Referer headers. Always send keys in the Authorization header or a dedicated request header.

X

JWTs with no expiry

Without exp, a stolen JWT is valid forever. Use short expiry (15–60 minutes for access tokens) and refresh tokens for long-lived sessions.

X

Storing secrets in JWT payloads

JWT payloads are Base64URL-encoded, not encrypted. Anyone who has the token can read the claims. Never put passwords, credit card numbers, or other sensitive data in JWT claims.

X

Skipping webhook signature verification

If you don't verify HMAC signatures on webhooks, any attacker can forge payloads to your endpoint. Always verify before processing payment events, user updates, or other sensitive webhook data.

X

Using OAuth when a simple API key would do

OAuth is complex and adds multiple moving parts. For internal service-to-service calls where there's no user delegation needed, a well-managed API key is simpler, easier to debug, and equally secure.

X

Accepting the "none" JWT algorithm

Some early JWT libraries accepted alg: none, allowing unsigned tokens. Explicitly allowlist the algorithms your server accepts (e.g., only HS256 or RS256) and reject everything else.

Frequently Asked Questions

Try These Tools

Related Guides and Comparisons