AI Tool Pipelines — Automate Your WorkflowsAI Tool Pipelines

JWT vs API Key vs OAuth2: Which to Use in Your Pipeline

7 min read · Updated Aug 5, 2026

Close-up of HTML and PHP code showing an authentication error and login form on screen

Use an API key when your own script or service calls an API on its own behalf. Use OAuth2 when your application needs to act on behalf of a specific end user of someone else’s service, with permission that user can revoke later. Use a JWT (JSON Web Token, a signed and self-contained blob of claims) when you need a token a server can verify locally without a database lookup on every request, which is often the exact token format OAuth2 hands back rather than a fourth, separate option. They are not three competing answers to the same question. They are answers to three different questions.

Key takeaways

  • An API key is one static secret that proves which application is calling, not which end user is behind it.
  • OAuth2 is a protocol for granting scoped, time-limited, revocable access on behalf of a specific user, without that user ever handing over a password.
  • A JWT is a token format, not a protocol: a base64url-encoded header, payload, and signature. It is commonly the exact access token OAuth2 issues.
  • Never trust a JWT’s payload before verifying its signature. Anyone can read (not forge) the claims inside, since they are only encoded, not encrypted.
  • A JWT cannot be revoked on its own once issued. It stays valid until it expires unless you build a separate blocklist, which erodes the point of using a self-contained token.
  • For a simple internal API between two services you control, an API key (or mutual TLS) is usually the right call. Save OAuth2 for delegated user consent.

Three different questions, not three competing answers

An API key answers "which application is this." OAuth2 answers "which application, acting for which user, with what permissions, for how long." A JWT answers a narrower question underneath both of those: "how is this token encoded so a server can verify it is genuine." That is why a JWT can show up inside an OAuth2 flow, inside a plain login system, or on its own with no OAuth2 anywhere near it. Confusing the format with the protocol is where most of the "which one should I use" confusion actually starts.

API key: proves which app, not which user

A static secret sent on every request, checked against a database of valid keys. No expiry unless the provider builds one in separately, no concept of an individual end user, no built-in way to scope permissions beyond whatever the provider lets you configure per key.

bash
curl https://api.example.com/v1/orders \
  -H "Authorization: Bearer sk_live_51Hxyz..."
The entire API key request pattern, in one line.

JWT: a self-contained, signed claim, not a protocol

A JWT is three base64url-encoded parts joined by dots: a header naming the signing algorithm, a payload of claims (user ID, expiry, scopes, whatever the issuer wants), and a signature over the first two parts. Because the signature covers the whole token, any server holding the signing key (or the matching public key, for asymmetric algorithms) can verify it locally, no call back to an auth server required. That is the entire appeal: it moves verification from "ask the database" to "check the math."

javascript
import jwt from 'jsonwebtoken';

function verifyAccessToken(token, publicKey) {
  return jwt.verify(token, publicKey, {
    algorithms: ['RS256'],
    issuer: 'https://auth.example.com',
  });
}

try {
  const claims = verifyAccessToken(incomingToken, JWT_PUBLIC_KEY);
  console.log('Authenticated as', claims.sub);
} catch (err) {
  console.error('Token rejected:', err.message);
}
Verifying a JWT correctly, with the algorithm pinned explicitly rather than trusted from the token itself.

The six weeks a "none" algorithm sat in production

In late 2019, a junior developer on a team I worked with, I will call him Daniel, wired up a resource server that verified an incoming token’s signature when the header said HS256, but fell through to accepting the payload with no verification at all when the header said none. It sat in production for about six weeks before a routine security review caught it. Nobody had exploited it yet, the team had just gotten lucky. The fix took ten minutes: hardcode the expected algorithm on the verify call and reject anything else, exactly the pattern in the code block above.

Close-up of PHP code on a monitor showing an authentication check

OAuth2: the protocol that often issues JWTs as its tokens

OAuth2 is the flow: redirect the user to the provider, they approve specific scopes, the provider redirects back with a code, your server exchanges that code for an access token. What OAuth2 does not mandate is the format of that access token. Plenty of providers issue an opaque random string you have to introspect via an API call. Plenty of others, including most identity platforms built after JWTs became common, issue a JWT as the access token specifically so resource servers can verify it locally instead of calling back to the auth server on every request.

Colorful programming code highlighted on a computer screen representing a decoded token payload

Side by side

What each one actually is, and where it fits.
FactorAPI keyJWTOAuth2
What it isA static secret stringA signed, self-contained token formatA protocol for delegated, scoped access
Answers the questionWhich app is callingIs this token genuine and unexpiredWhich app, for which user, with what scopes
RevocationManual, rotate the keyNot built in, valid until expiry unless blocklistedUser revokes access from their own account settings
Best fitServer-to-server, scripts, internal toolsStateless verification inside any auth systemThird-party integrations acting for a specific user

My honest opinion: do not reach for OAuth2 to protect an internal API between two services you control. That is what a rotated API key, or mutual TLS if you want to go further, is for. OAuth2 exists to solve delegated user consent, a genuinely hard problem, and using it to protect service-to-service traffic just adds a redirect flow and refresh-token logic nobody asked for. This holds as long as you own both ends of the connection. The moment a third party needs to call that internal API on a user’s behalf, revisit the decision, because that is exactly the problem OAuth2 was built to solve.

RFC 7519, the IETF specification that formally defines JWTs (published 2015), explicitly warns implementers not to trust the algorithm named in a token’s own header without validating it against an expected set first. That warning exists in the spec because the alg:none pattern above was common enough across early libraries to need calling out by name.

“An API key tells you which app is knocking. OAuth2 tells you which user let it in, and for how long. A JWT is just the envelope either one might hand you.”

Frequently asked questions

Frequently asked questions

Is a JWT the same thing as OAuth2?

No. OAuth2 is a protocol for granting delegated, scoped access. A JWT is a token format, a way of encoding claims so they can be verified with a signature. OAuth2 commonly issues JWTs as its access tokens, but plenty of OAuth2 providers issue opaque tokens instead, and JWTs are used plenty of places with no OAuth2 in the picture at all.

Can I use a JWT without OAuth2?

Yes. A JWT is just a signed token format. A plain email-and-password login system can issue a JWT on successful login and verify it on every subsequent request, with no OAuth2 redirect flow anywhere in the design.

Can an API key be a JWT?

They usually are not, but nothing stops it technically. Most API keys are opaque random strings by convention, since the point is a simple static secret. A JWT used as an API key would add signature verification overhead for little benefit in a server-to-server context that does not need per-request claims.

How do I revoke a JWT before it expires?

There is no built-in way, since verification happens by checking the signature rather than a database lookup. The common workarounds are keeping JWTs short-lived (minutes) paired with a revocable refresh token, or maintaining a blocklist of revoked token IDs that gets checked alongside signature verification.

Which one should I use for a simple internal API?

An API key, in most cases. It is the least complexity for a problem that does not involve a third party acting on behalf of an individual end user. Reach for OAuth2 only once a separate application needs delegated, user-scoped access to your API.

What is the JWT "alg: none" vulnerability?

Some early JWT libraries read the signing algorithm from the token’s own header and verified accordingly, including a "none" option intended for testing. An attacker could set that header, strip the signature, and have the token accepted as fully verified. The fix is to pass an explicit allow-list of accepted algorithms to the verification function rather than trusting the token to declare its own.