Refresh tokens
This version introduces refresh tokens, reduces access tokens time to live, and removes any tokens from local storage.
Context: Why I Made This Change
With Spider, security and privacy are at the core of everything I build — especially when it comes to authentication.
Previously, Spider's authentication API issued long-lived access tokens that were stored in both memory and browser storage.
While functional, this approach posed several risks:
- Long-lived tokens increase the blast radius of token leakage.
- Revocation was difficult, requiring full token invalidation mechanisms.
- XSS attacks were possible to fetch the token.
I wanted to align with modern best practices used by platforms like Google and GitHub:
- Short-lived tokens
- Secure, HttpOnly refresh tokens
- Session isolation and rotation
- Centralized revocation
How I did it: A Layered Security Redesign
I redesigned the authentication system around stateless access tokens and rotated refresh tokens, bound to individual sessions per device.
Key principles of the new system:
- Access tokens expire after a short time (~15 minutes).
- Refresh tokens are stored in HttpOnly, Secure cookies, inaccessible to JavaScript.
- Each session has a unique session ID, tracked securely in Redis.
- Refresh tokens are rotated at every use. Old ones are revoked immediately.
- Logout only revokes the current session, not all devices.
- Redis-backed store ensures tokens are centrally managed and revocable.
Schematic view
Login
└──> Provides:
├── Short-lived access token (JWT)
└── Refresh token (JWT in HttpOnly cookie)
└── Stored in Redis (indexed by jti and sessionId)
Access to UI
└──> Call `GET /sessions/token` to issue access token
├── Validates refresh token from cookie
├── Rotates token (new jti)
└── Issues new access token + refresh token
Access token close to expiry while on UI?
└──> Call `GET /sessions/token` to renew access token
└──> Renew impersonation and team tokens
User logs out
└──> Call `DELETE /sessions`
└── Uses access token to find sessionId
└── Revokes all refresh tokens in Redis for that session
What this means for you
- More secure by default
- Even if an access token leaks, it expires in minutes and cannot be refreshed without the securely stored cookie.
- Improved session visibility
- Every login from a browser or device is isolated, making future session management and revocation easier.
What's next
This foundation opens the door for future features:
- User-facing device/session management UI
- Login alerts for unknown devices
- Optional 2FA challenges per session
- Service accounts for scripts
I'm excited about what this unlocks and thankful to the community for helping Spider securely!