IntegrAuth Academy
Identity, security and practical AI — free, from zero. Byte-sized lessons, real diagrams, hands-on labs, zero fluff. Two programs, each with its own exam and certificate.
English is hard? Your browser can translate this page into Tamil, Telugu, Kannada, Malayalam or Hindi. Tech words stay in English so you learn the real names.
How?
- Chrome on phone: ⋮ menu → Translate
- Chrome on computer: right-click → Translate to …
- Edge: the translate icon in the address bar
Ways to authenticate an API
Maya's browser, Bot A's nightly job, Sam's partner server and Kai the AI agent all call one API. Each must prove who it is. Your goal: pick a sign-in method for a caller, and say why.
- Ask two things: who is calling, and what a stolen copy buys.
- Bearer secrets work for anyone who copies them.
- Proof of possession keeps the key at home.
- Platform-attested identity has no stored secret.
- Anything inside a browser or phone app is public.
Question 1: who is calling?
The caller can be an app, a person using an app, or a program running somewhere (a workload). An API key usually names only an app. A session cookie names a person in a browser. An access token can name both the app and the person it acts for.
Kai books a class for Maya. So Kai's credential should name both. It should be a token Maya allowed, never her password.
Question 2: what does a stolen copy buy?
The answer sorts methods into three families.
- Bearer secrets. The secret itself goes with every request. Examples: an API key, a password, a session cookie, a bearer token. Anyone with a copy can use it, like cash.
- Proof of possession. A private key stays at home. Each request carries only a fresh proof made with it. Examples: a signature, a TLS handshake, a DPoP proof. A copied proof is stale. It works once, or for one connection.
- Vouched for by the platform: platform-attested identity. The platform (a cluster, a cloud, a CI system) vouches for the code. It hands over a credential that lasts minutes. No long-lived secret sits in a file.
three ways to pay. Cash is a bearer secret: whoever holds it can spend it. A UPI payment is proof: you approve each payment fresh on your phone, so an old screenshot buys nothing. A hospital wristband is platform-vouched: the front desk checked you once, and every ward trusts the band until you leave.
The real upgrades
An access token is still a bearer secret. Three things really help. Shorter life: a copy dies by itself. Narrower permissions: a copy can do less. Proof of possession: a copy does not work at all.
Which method for which caller?
Stop at the first match.
- A person in your own web app? Use a hardened session cookie. Keep tokens on a backend-for-frontend server.
- Someone else's app acting for a user? Use OAuth authorization code with PKCE. Never ask for the user's password. The OAuth password grant must not be used.
- Your own service or job on a platform that can vouch for it? Use workload identity from the platform.
- A server from another company? Use client credentials with
private_key_jwtor mTLS, not a plain key. - Messages pushed to you, like webhooks? Use signatures over the raw body, with a timestamp.
- Public or low-risk data, only to count usage? Use a scoped API key in a header.
Go deeper: Four things people call a key
The word "key" has four jobs. Keep them apart.
🎫 An API key
A long random string from the server. It does no cryptography. It is a bearer secret sent on every call.
🤝 A shared secret key
Both sides hold it. You use it to compute an HMAC signature over each request. The secret itself is not sent. A leak on either side lets someone sign.
🔐 A key pair
A private key that stays with its owner, and a public key that anyone may see. The private key signs. The public key checks.
📜 A certificate
A public key plus a name, signed by an authority. Everyone who connects gets a copy. Only the private key behind it proves anything. See certificates and chains of trust.
When a partner says "we use keys", ask which kind. Where each one lives decides how easily it leaks. See guarding private keys.
Go deeper: The full menu
| Method | Good | Bad | Use it when… |
|---|---|---|---|
| API key a long random string in a header | Simple. Easy to count and cut off per key. | Often never expires. Names an app, not a person. Leaks into logs and repos. | Data is low-risk and you mainly count callers. See API keys vs OAuth. |
HTTP Basicuser:password, Base64-encoded | Every HTTP tool supports it. | A real password goes on every call. Base64 is encoding, not encryption. No expiry or scopes. | Internal tools, and a client signing in to a token endpoint. See the Authorization header. |
| Session cookie | The browser handles it. HttpOnly hides it from JavaScript. The server can end the session at once. | The browser adds it by itself, so you must defend against CSRF (use SameSite plus checks). Only fits your own site. | A person in your web app, best through a backend-for-frontend. See sessions and cookies. |
| Bearer access token opaque or JWT (RFC 6750) | Short-lived and scoped. Names the app and the user. | A copy works until it expires. A JWT cannot be taken back early. See opaque vs JWT. | Apps acting for users. The default for modern APIs. |
| Client credentials with a client secret | Standard OAuth. The secret goes only to the token endpoint. | The server keeps a copy too. A leaked secret can mint tokens until you rotate it. | A simple first step for machines. See machine login. |
| Client credentials with private_key_jwt | The client signs a short-lived assertion (RFC 7523). The server stores only the public key. | The client must manage a key and write signing code. | Partner machines that must not share secrets. |
| HMAC request signing | The secret never travels. The signature covers method, path, body and time. | Both sides hold the same secret. Both must sign the exact same bytes. | Webhooks and high-value calls. See signed requests. |
| Mutual TLS client certificates (RFC 8705 for OAuth) | The private key never leaves the client. The connection is checked first. | You must issue, rotate and revoke certificates (certificates). Proxies must pass identity on safely (TLS and mTLS). | Service-to-service and business-to-business APIs, and high-security profiles like FAPI. |
| Sender-constrained tokens DPoP (RFC 9449) or certificate-bound | A stolen token is useless without the matching key. | More moving parts. Not supported everywhere yet. | Where a leaked token would hurt a lot. See DPoP and mTLS binding. |
| Workload identity SPIFFE, federation | No stored secret. Credentials renew themselves. | Needs a platform that can vouch for workloads. | Your own services on a cluster, cloud or CI system. See workload federation and SPIFFE. |
RFC 9700 (January 2025) is the current OAuth security guide. It says servers SHOULD sender-constrain access tokens. It says signing in with a key pair (mTLS or private_key_jwt) is RECOMMENDED. Real systems often stack two methods, such as mTLS plus a token, or a DPoP-bound token plus rate limits at the gateway.
Go deeper: Seven questions to compare methods
- Who is the caller: a person, an app or a workload?
- Does the secret cross the wire, or only a proof?
- Can someone replay a captured request, and for how long?
- Can the old and new credential overlap while you rotate?
- How fast can you revoke one caller?
- How fine are the permissions?
- Do your libraries, gateways and partners support it?
The last one matters. If partners cannot use a method, they switch to a pasted key.
Sam's company wants to pull private order data every night. Their ticket says: "an API key, please". Zara says no, because a key that never expires is too risky. She offers client credentials with private_key_jwt. Each night Sam's server trades a signed assertion for a 10-minute token scoped to orders:read.
Anything inside a browser app or phone app is public. An API key, client secret or HMAC secret in that code can be pulled out. "Hiding" it does not help. Public apps get user-bound tokens through OAuth (with PKCE, ideally DPoP). A real secret stays on a server you control.
🧪 Interactive lab — enable JavaScript to play with this one.
Put each method of an API you use into one of the three families. Then build a private_key_jwt assertion with Client Assertion Check. Look inside a DPoP proof with DPoP Check.