Quick answer
An access token is a short-lived credential used to call protected APIs. A refresh token is a longer-lived credential used to get a new access token after the old one expires.
Access tokens should be easy to validate and short enough that token theft has limited impact. Refresh tokens should be stored more carefully because they can extend a login session.
Why two tokens exist
If an API issued one long-lived token, clients would not need to refresh often, but a stolen token could be used for a long time. If the API issued only very short-lived tokens, users would have to sign in too often.
The access-token plus refresh-token pattern separates those concerns:
- Access token: optimized for frequent API authorization.
- Refresh token: optimized for session continuity.
This is common in OAuth 2.0, OpenID Connect, mobile apps, single-page apps, and service architectures that need short-lived API credentials.
Main difference
| Token type | Primary job | Typical lifetime | Sent to APIs? | Security sensitivity |
|---|---|---|---|---|
| Access token | Authorize API requests | Minutes to hours | Yes | High |
| Refresh token | Get new access tokens | Hours to months | No, only token endpoint | Very high |
The refresh token is usually more sensitive because it can mint new access tokens. Treat it like a long-lived session secret.
Access tokens
An access token is presented when calling an API:
GET /api/profile
Authorization: Bearer eyJhbGciOi...
The API validates the token and checks whether it grants permission for the requested operation. Access tokens may be JWTs, opaque tokens, or another signed/encrypted format.
For many systems, access tokens include:
- Subject or user identifier.
- Issuer.
- Audience.
- Expiration time.
- Scopes or permissions.
- Tenant or account context.
Keep access tokens short-lived. If a token leaks through logs, browser storage, proxy headers, or client compromise, expiration limits the damage window.
Refresh tokens
A refresh token is sent to an authorization server or token endpoint, not to every API:
POST /oauth/token
Content-Type: application/json
{
"grant_type": "refresh_token",
"refresh_token": "rft_abc123"
}
If the refresh token is valid, the server returns a new access token and often a new refresh token.
Refresh tokens are useful because users can remain signed in without giving every API request a long-lived credential.
Token rotation
Refresh token rotation means the server issues a new refresh token every time the client refreshes. The old refresh token becomes invalid.
This helps detect theft. If an attacker steals an old refresh token and tries to use it after the legitimate client already rotated it, the server can detect reuse and revoke the token family.
A simplified flow:
- Client uses refresh token A.
- Server returns access token and refresh token B.
- Server marks refresh token A as used.
- If A is used again, the server treats it as possible compromise.
Rotation is especially important for browser-based and mobile clients.
Storage choices
Storage is one of the most important security decisions.
For browser apps, avoid storing sensitive tokens in places exposed to JavaScript when possible. localStorage is convenient, but an XSS bug can read it. HttpOnly, Secure, SameSite cookies reduce JavaScript exposure, but they require CSRF-aware design.
For mobile apps, use the platform’s secure storage primitives when available. For backend services, use secrets management or encrypted storage rather than plain configuration files.
There is no storage choice that makes poor application security safe. Token storage must be paired with XSS prevention, CSRF controls where relevant, TLS, logging hygiene, and short lifetimes.
Revocation
Access tokens can be hard to revoke immediately when they are self-contained JWTs. The API may validate the signature and expiration without checking a central store.
Common approaches:
- Keep access tokens short-lived.
- Revoke or rotate refresh tokens.
- Use token introspection for opaque tokens.
- Add a blocklist for high-risk events.
- Track session version or user security stamp.
Refresh tokens are easier to revoke because the authorization server usually stores or validates them centrally.
JWT access tokens vs opaque tokens
Access tokens are often JWTs, but they do not have to be.
JWT access tokens can be validated locally by APIs, which reduces lookup traffic and works well across services. The tradeoff is that claims can become stale until expiration.
Opaque access tokens are random-looking identifiers. APIs must call an introspection endpoint or shared store to validate them. This adds network or storage dependency, but revocation and centralized policy can be easier.
Use the format that fits your infrastructure and risk model. Token format is less important than expiration, storage, validation, and revocation behavior.
Common lifetimes
Exact lifetimes depend on risk, product needs, and compliance constraints, but a common starting point is:
| Credential | Example lifetime |
|---|---|
| Access token | 5 to 30 minutes |
| Refresh token for web app | Hours to days |
| Refresh token for mobile app | Days to weeks |
| Remember-me session | Weeks to months, with stronger controls |
Longer lifetimes increase convenience and risk. Higher-risk products should use shorter lifetimes, rotation, device tracking, and stronger re-authentication rules.
Common mistakes
The first mistake is using a refresh token as a normal API bearer token. Refresh tokens should only go to the token endpoint.
The second mistake is putting too much sensitive data inside an access token. A signed JWT is not automatically encrypted. If clients can read it, do not store secrets in it.
The third mistake is using long-lived access tokens because refresh logic feels inconvenient. That shifts complexity into security risk.
The fourth mistake is not rotating refresh tokens. Static long-lived refresh tokens are harder to defend after theft.
The fifth mistake is logging tokens. Authorization headers, token responses, and cookies should be redacted in logs.
Practical backend recommendation
For most backend systems:
- Use short-lived access tokens.
- Use refresh tokens only with the token endpoint.
- Rotate refresh tokens when possible.
- Store refresh tokens or token metadata server-side.
- Redact tokens from logs.
- Design logout and account-disable behavior explicitly.
- Prefer secure cookies for browser apps when the architecture supports them.
- Document token lifetimes and refresh behavior for clients.
The goal is not to make tokens complicated. The goal is to make token compromise less damaging and session behavior predictable.
Related reading
Read OAuth 2.0 Explained for Backend Developers for the authorization flows around these tokens and JWT vs Session Authentication for the broader architecture tradeoff. Use the JWT Decoder to inspect test access-token claims locally, remembering that decoding is not signature validation. For browser security risks around token storage and cookies, read CSRF vs XSS. For API behavior around authentication errors, read REST API Status Codes Explained. You can also browse the Authentication topic cluster for related backend security articles.