API Authentication: JWT, OAuth2, and API Keys Each Have a Job
API authentication is the area where implementation decisions have the most direct security consequences and where the choice of mechanism is most frequently driven by familiarity rather than fit. Teams that have used JWTs extensively reach for JWTs. Teams that have configured OAuth2 once and survived it reach for OAuth2. Teams that want something simple reach for API keys. Each choice reflects a different problem being solved, and using the wrong mechanism for the problem introduces either unnecessary complexity or genuine security gaps.
The distinction that clarifies the choice is between authentication — verifying that a request comes from a legitimate caller — and authorization — determining what that caller is permitted to do. Different mechanisms serve these concerns with different trade-offs.
API Keys: The Right Tool for Machine-to-Machine
API keys are the right authentication mechanism for server-to-server integrations where the calling service has a stable, known identity and the key can be stored securely. A backend service calling a third-party payment API, a data pipeline accessing an analytics platform, a CI system posting build results to a tracking service — these are contexts where an API key is appropriate, straightforward to implement, and sufficient for the security requirements.
The security properties of API keys are simple: the key authenticates the caller, and access control is applied by the API based on which key is presented. Key rotation is the primary security maintenance requirement. Keys that are never rotated are keys that can be compromised without detection.
The failure mode for API keys is the same across every organization that has experienced it: a key committed to a version control repository, included in a public repository, leaked through a log file, or embedded in a mobile application binary. These failures are not API key failures. They are secrets management failures. The appropriate response is secrets management discipline — environment variables, secrets vaults, rotation policies — not abandoning API keys for a different mechanism.
JWT: Stateless Authorization for Known Callers
JSON Web Tokens provide a mechanism for encoding claims — assertions about identity, roles, permissions, and expiration — in a signed token that the recipient can verify without calling back to an authorization server. The bearer of a valid JWT presents verifiable proof of their claimed identity and permissions in every request, without the latency of a database lookup or a network call to validate the session.
The stateless property is JWT’s primary advantage. An API that validates JWTs locally can scale horizontally without shared session state. This is the right design for systems where session lookup latency is a constraint and where the trade-off — losing the ability to revoke tokens before they expire — is acceptable.
The trade-off is real and frequently underestimated. A JWT cannot be invalidated before its expiration time without either maintaining a revocation list — which reintroduces the stateful lookup that JWT was chosen to avoid — or using very short expiration times that require frequent token refreshes. Teams that need immediate revocation capability — logging out a compromised user, revoking a service account — are not well-served by long-lived JWTs.
OAuth2: Delegated Authorization at the Right Scale
OAuth2 is not an authentication protocol. It is a delegated authorization framework. The confusion between the two is the source of most OAuth2 misimplementations. OAuth2 answers the question: can a third-party application access resources on behalf of a user, with the user’s explicit consent, without sharing the user’s credentials with the third-party? This is a specific and important problem. It is not the same problem as authenticating a machine-to-machine API call or validating a user’s identity in a first-party application.
OAuth2 is the right mechanism when a user needs to authorize a third-party application to access their data on another service — the social login pattern, the “connect your calendar” feature, the payment authorization flow. It is overengineered for first-party applications where the client and the authorization server are under the same organization’s control.
OpenID Connect, which adds identity claims on top of OAuth2, is the appropriate choice when OAuth2 is being used and authentication — verifying who the user is, not just what they are authorized to do — is also required. OIDC’s ID token provides the identity information that OAuth2’s access token deliberately does not.
The Decision
Server-to-server integration with a stable caller identity: API keys with secrets management discipline. Stateless authorization for a distributed API serving known callers: JWT with appropriate expiration policies. Third-party delegation, social authentication, or any flow where a user is authorizing access to their data: OAuth2 with OpenID Connect for identity. Using any of these for a problem it was not designed to solve is not a clever optimization. It is technical debt with a security surface.