Blog

API Authentication Methods Explained: Keys, Tokens, OAuth2

·11 min read

Why upstream authentication belongs at the gateway

Every API you call expects to be authenticated a specific way. One vendor wants an X-API-Key header, another wants a bearer token, a third runs OAuth2 with short-lived access tokens that need refreshing, and an internal service still uses HTTP basic auth. Scatter those secrets across application code and you end up with credentials in environment variables, bespoke refresh logic in every service, and no single place to rotate a key when it leaks.

RequestRocket moves that problem to the gateway. A target credential describes how the gateway authenticates to one upstream API. Your callers hit a proxy; the proxy attaches the correct upstream credential before forwarding the request. The secret never travels back to the caller, and it lives in exactly one place.

But before you can pick the right one, it helps to understand the authentication schemes themselves. Each is a small industry standard (or convention) with its own mechanics, history, and trade-offs. This post explains the main ones — what they are, how they work on the wire, and where each is a good or bad fit.

A quick mental model

Authentication answers one question: who is making this request? Nearly every HTTP API scheme answers it by attaching a secret to the request — in a header, a query parameter, or (occasionally) the body — that the server can check.

The schemes differ along a few axes:

  • Static vs. dynamic. Is the secret a fixed value you hold indefinitely, or a short-lived token that has to be fetched and refreshed?
  • Symmetric vs. delegated. Did the two parties share a secret directly, or did a third party (an identity provider) vouch for the caller?
  • Bearer vs. proof-of-possession. Can anyone who steals the token use it (a “bearer” secret), or must the caller prove they hold a private key?

Almost everything below is a bearer scheme: the token is the credential, so protecting it in transit (TLS) and at rest matters enormously.

API keys

An API key is the simplest scheme: a long, random, opaque string the provider issues to you, which you send on every request. It typically lives in a custom header such as X-API-Key, though some APIs accept it as a query parameter.

GET /v1/forecast HTTP/1.1
Host: api.weather.example
X-API-Key: sk_live_4c9a1f7b2e8d...

The server looks the key up in its own store and maps it to an account. There’s no expiry built into the scheme and no cryptography beyond the transport layer — the key’s only protection is its secrecy and the fact it travels over HTTPS.

Strengths: trivial to implement and use; no token exchange, no clock, no refresh. Weaknesses: it’s a bearer secret with no expiry, so a leaked key is valid until someone manually revokes it. Keys in query strings are especially risky because they end up in server logs and browser history. Best suited to server-to-server calls where the key can be stored securely and rotated on a schedule.

Bearer tokens

“Bearer” is an authentication scheme name defined alongside OAuth 2.0 (RFC 6750). The idea is in the name: whoever bears the token may use it. The token goes in the standard Authorization header behind the word Bearer.

GET /v1/contacts HTTP/1.1
Host: api.crm.example
Authorization: Bearer pat-na1-3f2a9c...

In practice “bearer token” covers two situations. Some providers issue you a long-lived personal access token or service token that you treat much like an API key — paste it once, use it indefinitely. Others use bearer tokens as the output of a flow like OAuth2, where the token is short-lived and refreshed automatically.

The Bearer prefix is a convention, not a law; some APIs use a different scheme word (for example Token) in the same header position. Strengths: standardised header, widely understood, works with any HTTP client. Weaknesses: like all bearer credentials, interception equals compromise — which is why short-lived tokens (OAuth2) are preferred over long-lived ones where the provider supports them.

HTTP basic authentication

Basic auth is one of the oldest HTTP schemes (RFC 7617). The client takes a username and password, joins them with a colon, Base64-encodes the pair, and sends it in the Authorization header behind the word Basic.

GET /reports/daily HTTP/1.1
Host: billing.internal.example
Authorization: Basic c3ZjX3JlcG9ydGluZzpzM2NyZXQ=

It’s important to understand that Base64 is not encryption — it’s trivially reversible encoding. Basic auth is only safe over HTTPS, where TLS protects the header in transit. Because the credentials are sent on every single request, a compromised connection exposes the password directly (unlike token schemes, where a leaked token can at least be revoked without changing the underlying password).

Strengths: universally supported, dead simple, no token lifecycle. Weaknesses: transmits reusable credentials repeatedly; no built-in expiry or scoping. It survives mostly in legacy and internal systems, and for machine accounts where a username/password pair is the only option.

JSON Web Tokens (JWT)

A JWT (RFC 7519) is not a transport scheme — it’s a token format. It’s a compact, URL-safe string of three Base64URL-encoded parts separated by dots: a header, a payload of “claims”, and a signature.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.SflKxwRJSMeKKF2QT4...

The payload carries claims such as sub (subject/user), iss (issuer), aud (audience), and exp (expiry). The signature is created by the issuer using either a shared secret (HMAC) or a private key (RSA/ECDSA). Anyone can read a JWT — it isn’t encrypted — but only a holder of the key can forge one, and any party with the public key or shared secret can verify it without calling back to the issuer. That self-contained, offline-verifiable property is what makes JWTs popular.

JWTs are usually transported as bearer tokens in the Authorization header. In an outbound context you might hold a signed JWT issued to you and present it to a partner API on each call.

Strengths: stateless verification, carries claims and expiry, cryptographically tamper-evident. Weaknesses: it’s still a bearer token if stolen; tokens can’t be easily revoked before they expire (unless the verifier maintains a blocklist); and the payload is readable, so it must never contain secrets.

OAuth 2.0

OAuth 2.0 (RFC 6749) is the big one — and the most misunderstood, because it’s not a single method but a framework of flows (“grant types”) for obtaining an access token. The common thread: instead of handing your credentials to the API, you exchange something at an authorization server’s token endpoint for a short-lived access token, then send that token (usually as a bearer token) to the API.

The reason it looks complex is that different scenarios need different flows:

  • Client credentials. Pure machine-to-machine. The client sends its own client_id and client_secret to the token endpoint and gets back an access token. No user is involved. This is the workhorse for backend integrations.
  • Resource owner password. The client collects a user’s username and password and exchanges them (plus its client credentials) for a token. It’s discouraged in modern designs because the client sees the password, but it persists for trusted first-party and legacy systems.
  • Authorization code. The gold standard for user-delegated access. The user is redirected to the provider’s login page, authenticates there, and the provider sends back a short-lived authorization code. The client swaps that code (with its secret) for tokens. The user’s credentials never touch the client — this is how “Sign in with Google/Microsoft” style delegation works.
  • PKCE (Proof Key for Code Exchange). An extension to the authorization-code flow for public clients (mobile apps, SPAs) that can’t safely hold a client secret. The client generates a random code_verifier, sends its hash up front, and reveals the verifier when redeeming the code — proving the same party that started the flow is finishing it.

Most flows also return a refresh token: a longer-lived credential used to obtain fresh access tokens once the short-lived one expires, without repeating the whole flow. Machine flows (client credentials, password) can simply re-request a token; user flows (authorization code, PKCE) rely on the refresh token, and when it lapses the user must sign in again.

On the wire, the API request itself looks unremarkable — the complexity is all in acquiring the token:

GET /v1/files HTTP/1.1
Host: api.provider.example
Authorization: Bearer eyJhbGciOi...

Strengths: short-lived tokens limit the blast radius of a leak; delegation means third parties never see user passwords; scopes constrain what a token can do. Weaknesses: operationally heavier — you must manage token endpoints, expiry, refresh, and clock skew. That token lifecycle is exactly the kind of work a gateway is well-placed to handle on your behalf.

Custom token schemes

Plenty of APIs — especially older or in-house ones — do something token-shaped that predates or ignores the OAuth2 spec. A typical pattern: POST your credentials to a /login endpoint, receive a token in the JSON response, then send that token on subsequent calls until it expires.

POST /v1/login HTTP/1.1
Host: api.vendor.example
Content-Type: application/json

{ "user": "svc", "secret": "..." }
{ "data": { "access_token": "abc123", "expires_in": 3600 } }

Conceptually this is the same idea as OAuth2’s client-credentials flow — exchange a durable secret for a short-lived token — but the request shape, the location of the token in the response, and the expiry field all vary per vendor. Handling it well means knowing where the token lives in the response and how the API expresses expiry (seconds from now, absolute timestamp, milliseconds, ISO date) so the token can be refreshed before it lapses.

Strengths: flexible enough to fit non-standard APIs; still gets you short-lived tokens. Weaknesses: no interoperability — every integration is bespoke, and there’s no shared library that “just works” the way OAuth2 clients do.

Custom and static-header schemes

Some APIs authenticate with a combination of fixed values rather than a single credential: several static headers, a client identifier plus a region hint, or pre-computed signing headers. A common member of this family is HMAC request signing (used by, among others, AWS Signature v4), where the client computes a keyed hash over parts of the request and sends the signature in a header. The server recomputes it to verify both the caller’s identity and that the request wasn’t tampered with — a rare example of a non-bearer scheme, because the shared key is never transmitted.

The unifying idea is that authentication material isn’t one tidy token; it’s whatever set of headers, parameters, or body fields the provider specified. Strengths: can express almost anything, including proof-of-possession signing. Weaknesses: entirely provider-specific, and signing schemes in particular are fiddly to implement correctly.

No authentication

Not every API requires credentials. Public data APIs — reference data, open government datasets, some read-only endpoints — accept anonymous requests. The scheme here is simply nothing: the request is sent as-is.

“No auth” is worth naming explicitly because unauthenticated does not mean ungoverned. Even for open APIs, teams often still want rate limiting, logging, and observability around the traffic — the authentication layer being empty doesn’t remove the value of everything else a gateway does.

Inbound vs. outbound authentication

One distinction trips people up. Everything above describes outbound authentication: how you prove your identity to an upstream API. There’s a mirror-image concern — inbound authentication — where a service verifies the identity of callers hitting it.

JWT verification is the classic inbound case: a service receives a JWT from a caller, checks its signature against the issuer’s public keys (often published at a JWKS URL), validates the expiry and audience, and reads the claims to decide what the caller is allowed to do. Note the direction: outbound JWT usage means presenting a token you hold; inbound verification means validating a token someone presented to you. They use the same token format but sit on opposite sides of the request.

Choosing between them

The practical decision usually comes down to what the upstream supports and whether the secret is static or short-lived.

SchemeWhat it sendsToken lifecycleTypical fit
API keyOpaque key in a header/paramStaticSimple server-to-server access
Bearer tokenToken in Authorization headerStatic or refreshedPersonal/service tokens; OAuth2 output
Basic authBase64 user:passwordStaticLegacy and internal systems
JWTSigned, claim-carrying tokenUsually short-livedStateless, verifiable identity
OAuth 2.0Access token from a token endpointShort-lived + refreshStandards-based, delegated, or M2M access
Custom tokenToken from a non-standard loginShort-livedVendor-specific token APIs
Custom/staticFixed headers/params, or a signatureStaticBespoke or signed requirements
NoneNothingN/APublic, unauthenticated APIs

As a rule of thumb: prefer short-lived tokens (OAuth2) over long-lived bearer secrets where you have the choice, always use TLS, and put the credential somewhere it can be rotated without a code change. Static secrets (key, bearer, basic) are the easiest to adopt but the most damaging to leak; dynamic schemes (oauth2, custom token) are more work to operate but fail safer.

Next steps

Understanding the schemes is half the battle; operating them — storing secrets safely, refreshing tokens before they expire, and rotating credentials without downtime — is the other half. That’s the part a gateway is built to absorb. Read the RequestRocket documentation to see how each of these maps to a managed credential, or start for free.

Enhance ISO 27001
Enhance SOC 2
Enhance GDPR
Enhance HIPAA

Add outbound API security
without changing code

Start on your own or talk to our team about improving the security of every API call you make.