Prompt
How do I manage sessions and refresh tokens for users?
Latest observation
Oct 6, 2026
OpenAI APIWeb search: off
A solid way to manage sessions and refresh tokens is to treat them as separate concerns:
- Access token = short-lived proof used on every API request
- Refresh token = longer-lived credential used only to get a new access token
- Session = the server-side record of a logged-in device/browser
Recommended approach
1) Use short-lived access tokens
- Lifetime: 5–15 minutes
- Sent with API requests
- If stolen, damage is limited
2) Use refresh tokens with rotation
- Lifetime: days to weeks
- Stored securely and used only at a refresh endpoint
- Every time a refresh token is used, issue:
- a new access token
- a new refresh token
- Invalidate the old refresh token immediately
This is called refresh token rotation and helps detect token theft.
3) Store sessions server-side
Keep a database record per session, such as:
session_iduser_idrefresh_token_hashcreated_atexpires_atrevoked_atdevice_infoip_address/last_seen_at
This lets you:
- log out one device
- log out all devices
- inspect active sessions
- revoke compromised sessions
Secure storage
Browser apps
- Store refresh tokens in HttpOnly, Secure cookies
- Avoid localStorage for refresh tokens if possible
- Use
SameSite=LaxorSameSite=Strictdepending on your flow
Mobile/desktop apps
- Store refresh tokens in OS secure storage:
- iOS Keychain
- Android Keystore / EncryptedSharedPreferences
- Windows Credential Manager, etc.
Typical flow
Login
- User authenticates with password / MFA / SSO
- Server creates a session
- Server issues:
- access token
- refresh token
- Refresh token is stored hashed in DB and sent to client securely
API request
- Client sends access token
- Server verifies it
- If valid, request succeeds
Refresh
- Access token expires
- Client calls refresh endpoint with refresh token
- Server checks:
- token exists
- not revoked
- not expired
- matches stored hash
- Server rotates token and returns a new pair
Logout
- Client calls logout
- Server revokes session and associated refresh token
- Client deletes local tokens/cookies
Important security practices
- Hash refresh tokens in the database
Store only a hash, not the raw token. - Rotate refresh tokens on every use.
- Detect reuse
If an old refresh token is reused, assume compromise and revoke the whole session family. - Bind sessions to context where practical:
- device ID
- user agent
- approximate location
- Require re-authentication for sensitive actions.
- Use TLS everywhere.
- Rate-limit refresh and login endpoints.
- Expire idle sessions and enforce absolute max lifetime.
Common pattern for token structure
- Access token: JWT or opaque token
- Refresh token: usually opaque random string
Many systems prefer:
- JWT access token for stateless authorization
- Opaque refresh token for server-side control
When to use server sessions vs JWT-only
Use server sessions + refresh tokens if you need:
- logout control
- device management
- immediate revocation
- higher security
Use JWT-only only if you accept:
- harder revocation
- more distributed trust
- simpler stateless verification
A practical default setup
If you want a good baseline:
- Access token: 10 minutes
- Refresh token: 30 days
- Refresh rotation: yes
- Storage:
- browser: HttpOnly Secure cookie
- backend: hashed token in DB
- Logout: revoke session row
- Reuse detection: revoke entire session family
If you want, I can also show:
- a database schema for sessions/refresh tokens, or
- an implementation example in Node.js, Python, Go, or Java.