API authentication is the mechanism that decides which caller a request belongs to, and it is where a large share of API breaches originate, either because the scheme was weak, the credentials were long-lived and over-scoped, or the token validation had a bypass. Choosing an authentication method is really choosing your blast radius: a leaked static key with full access is a catastrophe, while a leaked short-lived, narrowly scoped, sender-bound token is a shrug. The methods below are ordered roughly from simplest to strongest, and the right answer for most APIs is a deliberate combination rather than any single one.
The short answer for 2026: prefer short-lived OAuth bearer tokens over static API keys, scope every credential to the minimum it needs, store secrets hashed and never in URLs, validate JWTs strictly (pin the algorithm, verify signature, check claims), and add mTLS or request signing for high-value machine-to-machine traffic. Here is how to implement each safely.
API keys: acceptable if you treat them like passwords
Static API keys are fine for low-risk, server-to-server use if you handle them correctly. That means each key is scoped to specific operations, tied to one client, rotatable without downtime, and stored on the server as a hash, never in plaintext, so a database leak does not hand over working credentials.
Authorization: Bearer sk_live_9f2c... # sent in a header, never in the URL query string
Never put keys in query strings, because URLs land in server logs, proxy logs, and browser history. Rate-limit per key so a leaked key cannot be used to scrape or brute-force at scale, and give each key an expiry so forgotten credentials do not live forever.
Bearer tokens: short-lived beats static
For anything user-facing or higher-risk, use OAuth 2.0 bearer tokens (typically via the client credentials or authorization code flow) instead of static keys. The advantage is lifetime: an access token measured in minutes limits the value of a leak far more than a key that works until someone remembers to revoke it. Pair short access tokens with refresh token rotation, and constrain tokens with DPoP or mTLS where supported so a stolen token cannot simply be replayed.
JWTs: the validation is the security
JSON Web Tokens are convenient because they are self-contained, and dangerous for exactly the same reason: if you trust a token's contents without rigorously verifying it, an attacker forges identities at will. Two classic failure modes define JWT security. The first is the alg: none bypass, where a server accepts a token that claims to be unsigned. The second is algorithm confusion, where a server that expects an RS256-signed token is tricked into verifying an HS256 token using the public key as the HMAC secret. Both let an attacker mint valid-looking tokens.
Library bugs compound this. CVE-2022-23529, a high-severity issue in the widely used jsonwebtoken package in versions before 9.0.0, stemmed from how the verification function handled the key parameter; version 9.0.0 added stricter checks. Keeping the library current is part of the control, not separate from it.
Validate defensively: pin the accepted algorithm explicitly, verify the signature, and check exp, nbf, iss, and aud on every request.
// Verify a JWT with the algorithm pinned and claims checked
const payload = jwt.verify(token, publicKey, {
algorithms: ["RS256"], // never accept a token's self-declared alg
issuer: "https://auth.example.com",
audience: "https://api.example.com",
});
mTLS and request signing for machine-to-machine
For high-value internal or partner APIs, raise the bar beyond bearer credentials. Mutual TLS authenticates the client with a certificate at the transport layer, so a request from an unrecognized client is rejected before your application logic runs. Alternatively, HMAC request signing has the client sign the method, path, body hash, and a timestamp with a shared secret, which both authenticates the caller and prevents tampering and replay when you enforce the timestamp window.
API authentication checklist
| Practice | Why |
|---|---|
| Scope every credential minimally | Limits blast radius of a leak |
| Prefer short-lived tokens over static keys | Shrinks the useful lifetime of stolen credentials |
| Store secrets hashed, never in URLs | Prevents log and history leakage |
| Pin JWT algorithm and verify all claims | Blocks alg: none and algorithm-confusion forgery |
| Keep auth libraries patched | Closes bugs like CVE-2022-23529 |
| Rotate keys and refresh tokens | Makes leaked credentials expire and detectable |
| Rate-limit per credential | Contains scraping and brute force |
| Use mTLS or signing for M2M | Stops replay and unauthenticated callers |
How Safeguard helps
API authentication depends on both correct configuration and the libraries implementing it. Safeguard's software composition analysis tracks the JWT, OAuth, and crypto libraries in your dependency graph and flags versions with known authentication CVEs like jsonwebtoken CVE-2022-23529, with reachability so you address the exploitable ones first, and autonomous auto-fix opens a tested pull request to bump them. Dynamic application security testing probes your live API endpoints for weak or missing authentication, and Griffin AI explains each finding and its fix. Developers enforce the same checks in CI with the Safeguard CLI.
Lock down how your APIs authenticate: get started free or read the documentation.
Frequently Asked Questions
Are static API keys ever acceptable?
Yes, for low-risk server-to-server traffic, provided you treat them like passwords: scope each key to the minimum operations it needs, tie it to one client, store it hashed rather than in plaintext, rate-limit per key, give it an expiry, and make rotation possible without downtime. For user-facing or higher-risk cases, prefer short-lived OAuth bearer tokens instead.
How do I validate a JWT securely?
Pin the accepted algorithm explicitly rather than trusting the token's own alg field, verify the signature against the correct key, and check the exp, nbf, iss, and aud claims on every request. This defeats the alg: none bypass and the RS256-to-HS256 algorithm-confusion attack, which are the two classic JWT forgery techniques.
Why does keeping my auth library updated matter?
Because token validation bugs live in libraries, not just your code. CVE-2022-23529 in jsonwebtoken before 9.0.0, for example, involved how the verification function handled the key parameter, and version 9.0.0 added stricter checks. A stale auth library can undermine otherwise correct validation logic, so patch it as a first-class control.
When should I use mTLS or request signing instead of bearer tokens?
Use them for high-value machine-to-machine or partner APIs where a replayed bearer token would be especially damaging. Mutual TLS authenticates the client by certificate at the transport layer, and HMAC request signing binds each request to a signed timestamp and body hash, preventing tampering and replay. Both raise the bar well above a portable bearer credential.