Loading...

Skip to content
MemonaIQ
ToolsLearnCompany
Sign in
ToolsLearnCompanyBrowse all tools
Knowledge Center
In this topic
APIs
What is an API? Definition, examples and how it worksREST API design principles: URLs, methods and errorsAPI authentication: API keys vs OAuth 2.0 vs JWTAPI rate limiting: algorithms, 429 and Retry-AfterWebhooks explained: signatures, retries and idempotencyOpenAPI breaking changes: what breaks API clientsRequest vs response schema compatibility in APIsHow enum changes break API clients and generated SDKsOpenAPI 3.0 vs 3.1: differences and migration checklistMCP stdio vs Streamable HTTP: transport security compared
A-Z glossary
HomeKnowledgeAPIs
APIs•5 min read•advanced

API authentication: API keys vs OAuth 2.0 vs JWT

API keys identify an app, OAuth 2.0 issues scoped tokens, and a JWT is a token format. When to use each, how to validate a JWT, and where to store tokens.

API keys, OAuth 2.0 and JWTs solve different problems

An API key is a long-lived secret that identifies the calling application. OAuth 2.0 is a framework for issuing short-lived access tokens with limited scopes, often on behalf of a user. A JWT (JSON Web Token) is a token format, a signed set of claims, that OAuth servers often use for those access tokens.

That leaves two separate decisions. The first is how clients get credentials: an API key or an OAuth flow. The second is how your API checks them: a JWT it validates itself, or an opaque token it looks up.

API keys: simple and coarse

An API key is a random string sent with every request, usually in the Authorization header or a custom header such as X-API-Key. It identifies a project or account rather than a person, and it stays valid until someone revokes it.

Keys suit server-to-server calls to a provider and fit poorly anywhere code runs on a user's device. Anyone can read code shipped to a browser or a mobile app, so a key inside it is public.

Store keys in a secrets manager or environment variables, give each one the narrowest permissions the provider offers, and rotate them. Keep keys out of query strings, because URLs end up in server logs, proxies and browser history.

OAuth 2.0: pick the flow that fits the client

OAuth 2.0 (RFC 6749) gives a client an access token from an authorization server, so an app acting for a user never handles the user's password. The token carries scopes, such as orders:read, that limit what it can do, and it expires.

The OAuth security best current practice, RFC 9700, says clients should not use the implicit grant and must not use the password grant. OAuth covers authorization; for signing users in, OpenID Connect adds an ID token on top of it. Two flows cover most cases:

  • Authorization code with PKCE, for apps acting for a user: server-rendered web apps, single-page apps and mobile apps. The user signs in at the authorization server, the app receives a one-time code, and it exchanges the code for tokens. PKCE (RFC 7636) binds the code to the app instance that started the flow, so an intercepted code is useless to anyone else.
  • Client credentials, for service-to-service calls with no user involved. The service authenticates with its own client ID and secret, or a private key, and receives a token for its own access.

How to validate a JWT

A signed JWT has three base64url-encoded parts separated by dots: a header, a payload of claims and a signature. Anyone holding the token can decode the payload, so never put secrets in it.

Use a maintained JWT library and configure each check explicitly instead of trusting its defaults. RFC 8725 collects the current best practices. Accept a token only when all of these hold:

  • The signature verifies with a key you trust, such as one your authorization server publishes, using the one algorithm you expect, such as RS256 or ES256.
  • The algorithm comes from your configuration. A token whose alg header says none, or names an algorithm you didn't configure, is rejected; letting the header choose allows algorithm-confusion attacks.
  • exp is in the future and nbf, if present, is not, allowing only a small clock skew.
  • iss matches your authorization server exactly.
  • aud includes your API, so a token issued for another service can't be replayed against yours.
  • The scopes or other claims permit the operation being called.
decoded-jwt-payload.json
json
{
  "iss": "https://auth.example.com/",
  "sub": "user_8412",
  "aud": "https://api.example.com",
  "scope": "orders:read",
  "iat": 1767222000,
  "exp": 1767225600
}

Where to store tokens, and where not to

Where a token lives decides who can steal it. In a server-rendered web app, keep tokens on the server and give the browser a session cookie marked HttpOnly, Secure and SameSite.

HttpOnly stops scripts from reading the cookie, but injected script can still send requests that carry it. You still need protection against cross-site scripting (XSS), plus SameSite or CSRF tokens against cross-site requests.

Single-page apps are harder. Any script on the page can read tokens in localStorage or sessionStorage, so one XSS flaw exposes them. Holding tokens in memory narrows that risk but loses them on reload. A backend-for-frontend, a small server that holds tokens and calls the API for the browser, keeps them out of the browser entirely.

Mobile apps should use the platform's protected storage: the Keychain on iOS and storage backed by the Keystore on Android. Never put tokens in URLs, logs, analytics events or source control.

Revoking self-contained tokens

A JWT access token is self-contained: the API validates it with a public key and never asks the authorization server. That is fast, but the API can't see that a token was revoked, so a stolen JWT keeps working until it expires.

The usual answer is short access token lifetimes, often minutes, paired with refresh tokens that the authorization server can revoke. Cutting access sooner means adding a lookup back in:

  • A deny list of revoked token IDs (the jti claim), checked on each request
  • Opaque tokens checked with token introspection (RFC 7662), where revocation takes effect on the next check at the cost of a network call or a short cache
  • Rotating the signing key, which invalidates every token signed with it at once
Previous guide
REST API design principles: URLs, methods and errors
Next guide
API rate limiting: algorithms, 429 and Retry-After
MemonaIQ tools

Try it on your own input

Check what this guide describes against your own URL, domain, code or file.

AI-Generated Code Risk Scanner

Check code for API keys, tokens and private keys written into the source before you commit or share it.

Open tool

References

  • RFC 9700: Best Current Practice for OAuth 2.0 Security
  • RFC 7519: JSON Web Token (JWT)
  • RFC 8725: JSON Web Token Best Current Practices

On this page

API keys, OAuth 2.0 and JWTs solve different problemsAPI keys: simple and coarseOAuth 2.0: pick the flow that fits the clientHow to validate a JWTWhere to store tokens, and where not toRevoking self-contained tokens
Updated:2026-10-25
Format:Technical Guide
Related tool
AI-Generated Code Risk Scanner

Check code for API keys, tokens and private keys written into the source before you commit or share it.

Open tool
MemonaIQ

Focused tools for everyday digital work.

  • 18 focused tools
  • 9 run in your browser
Browse all tools Get help

Featured tools

URL Intelligence PlatformImage CompressorInvoice StudioDNS LookupAI Token Counter

Explore

All toolsKnowledge CenterGuidesResourcesCompany

Support

HelpContactSecurity

Legal

PrivacyTermsCookies

© 2026 MemonaIQ. Made in Colombo.

Back to top

MemonaIQ