Token-Based Authentication
Token-based authentication means the client gets a token after login and sends it with every request. Instead of a cookie that the browser handles automatically, the client attaches the token itself, usually in a request header.
How It Works
- User sends username and password.
- Server verifies them and generates a token (a long random string).
- Server returns the token in the response body.
- Client stores the token and sends it in the Authorization header on every request.
- Server validates the token and identifies the user.
The word Bearer means "whoever holds (bears) this token gets access". So a token is like a movie ticket: the gate checks the ticket, not your name.
Two Kinds of Tokens
| Opaque Token | Self-Contained Token (JWT) | |
|---|---|---|
| What it looks like | Random string: tk_9f3a... | Encoded data + signature |
| Contains user info? | No, just a reference | Yes (user ID, roles, expiry) |
| How server validates | Looks it up in a token store (Redis/DB) | Verifies the signature, no lookup |
| Revoke instantly? | Yes, delete from store | Hard, valid until it expires |
Opaque tokens still need a lookup, so they are close to sessions in behavior. Self-contained tokens are what make token auth truly stateless. We cover them in detail on the JWT page.
Access Token + Refresh Token
Tokens should be short-lived so a stolen one is useful only briefly. But logging in every 15 minutes is annoying. So systems use two tokens:
| Token | Lifetime | Used for |
|---|---|---|
| Access token | Short (5–15 min) | Calling APIs on every request |
| Refresh token | Long (days/weeks) | Getting a new access token |
1Access token expires → client sends refresh token to /refresh2→ server checks refresh token (stored server-side, can be revoked)3→ returns a new access token → user stays logged inLogout = delete the refresh token on the server. The access token dies on its own within minutes.
Why Tokens Scale Well
With self-contained tokens, any server can validate the request without asking a shared store.
No sticky sessions, no session lookup per request. This is why tokens are popular with microservices and mobile apps.
Security Basics
- Always use HTTPS, because anyone holding the token can use it.
- Keep access tokens short-lived.
- Where to store on the client:
- localStorage: easy, but readable by JavaScript (risky if there's an XSS bug).
- HttpOnly cookie: safer from XSS, but then you need CSRF protection.
- Mobile apps: secure storage (Keychain / Keystore).
- Rotate refresh tokens: issue a new one each time it's used, and reject the old one.
Session vs Token
| Session-Based | Token-Based | |
|---|---|---|
| State | Stored on server | Carried by client (if self-contained) |
| Sent as | Cookie (automatic) | Authorization header |
| Scaling | Needs shared store or sticky sessions | Any server can validate |
| Revocation | Instant | Hard for self-contained tokens |
| Best for | Browser web apps | APIs, mobile, microservices |
Pros and Cons
| Pros | Cons |
|---|---|
| Stateless, scales horizontally | Hard to revoke before expiry |
| Works for web, mobile, and APIs | Stolen token = full access until expiry |
| No per-request lookup (self-contained) | Bigger than a session ID |
| Easy to share across services | Needs refresh-token logic |
When to Use It
- REST APIs consumed by mobile apps or SPAs
- Microservices that each need to verify the user
- Systems with many servers behind a load balancer
Next, we'll open up the most popular self-contained token, JWT , and see what's inside it.