Bearer token
A credential where possession alone proves identity. Anyone who holds the token can use it. API keys, OAuth access tokens, session cookies, and most personal access tokens are all bearer tokens.
What it is
A bearer token is a credential where possession alone proves identity. Anyone who holds the token can use it to authenticate. The receiving server has no way to distinguish the legitimate holder from someone who copied the token off a laptop, intercepted it in transit, or grepped it out of a log file.
The name comes from RFC 6750, which defines OAuth 2.0 bearer tokens: "Any party in possession of a bearer token (a 'bearer') can use it to get access to the associated resources." The same model predates the RFC by decades; it's how cookies, API keys, and most session credentials have always worked.
Common kinds
The category is broader than the name suggests:
- API keys. Long opaque strings like
sk_live_abc123...orxoxb-...that a client sends in anAuthorization: Bearerheader or a custom header. - OAuth access tokens. Short-lived JWTs or opaque strings issued after a user signs in to a delegated app, used to call APIs on the user's behalf.
- Session cookies. The cookie a browser sends after login. Mechanically identical to a bearer token: possession of the cookie grants access for its lifetime.
- JWTs (in many uses). A JWT signed by an authorization server and passed to resource servers is structurally a bearer token. The signature proves the issuer minted it; it doesn't prove the holder is who the token says they are.
- Personal access tokens. GitHub, GitLab, Slack PATs. Long-lived bearer credentials scoped to a user account.
- Webhook tokens. A static token in a query string or header that a receiver checks to verify the request came from the expected sender.
A short-lived bearer token is still a bearer token. Reducing the lifetime narrows the abuse window but doesn't change the model.
Why they work
Bearer tokens are the dominant auth pattern on the internet for three reasons:
- They work over any transport. A string in an HTTP header travels through every proxy, CDN, load balancer, and service mesh without modification.
- They're trivial to implement. Server checks the value against a stored hash; that's the whole verification step. No cryptography on the client beyond TLS.
- They compose with existing tools.
curl, language HTTP clients, every API testing tool. All natively support sending a header.
If credentials never leaked, bearer tokens would be the right answer. They're simple, fast, and universally supported.
How they fail
Bearer tokens fail through leakage. The structural problem is that the server only sees the token, so it can't tell the legitimate client from anyone else holding the same string.
Common leak paths:
- Server logs. A token sent in a URL parameter ends up in every access log along the way.
- Browser developer tools. Anyone with shoulder-surfing access to a developer console can copy the token.
- Error reports and crash dumps. Sentry, Bugsnag, mobile crash reporters. Tokens in request payloads end up in the error report.
- Intercepting proxies. Corporate MITM proxies that terminate TLS see every bearer token going through them.
- Screenshots and screen recordings. Support tickets and demo videos routinely include tokens by accident.
- Process memory dumps. A core dump of a running service contains every credential the process holds.
When any of these leak, the attacker uses the token exactly the same as the legitimate client, and there's no way for the receiving server to tell them apart. Detection and rotation are the only mitigations.
Various patterns try to harden the model: short expiry windows, IP allowlists tied to the token, refresh tokens that require a second credential to issue new access tokens, audience restrictions in JWTs. Each helps but doesn't change the fundamental property that the credential is the proof.
What replaces them
The structural alternative is signed requests. The client holds a private key, and each request carries a signature proving that key was used to sign that specific request. The credential never travels with the request, so capturing the request is useless. SSH, AWS Signature v4, modern HTTP Message Signatures (RFC 9421), and most machine-to-machine systems built in the last decade use this pattern.
Bearer tokens still make sense at the user-experience layer (a browser holding a session cookie can't reasonably do per-request signing). For machine-to-machine auth, signed requests are the better default.
How SikkerKey treats them
In SikkerKey, machine reads aren't authenticated with a bearer token. Each machine carries an Ed25519 private key generated locally during bootstrap and signs each request with method:path:timestamp:nonce:body_hash. SikkerKey verifies the signature against the public key on file. A captured request is useless five minutes later (timestamp window) and useless on any other request (signature is bound to the contents). Copying credentials off a laptop or grepping logs for tokens turns up nothing that reads your secrets.
Bearer tokens still exist in SikkerKey at the user layer (dashboard sessions use them, like any web app), but the path your secrets traverse is signature-only.
See also
SikkerKey is the secrets manager built around the patterns in this glossary. Encrypted vault, machine identity over signed requests, dynamic secrets — set up in minutes.
Start for Free