Understanding the concept of Refresh & Access Token
In modern web development, security and user experience often seem at odds. You want your users to stay logged in for weeks (User Experience), but you also want to ensure that if their credentials are stolen, an attacker can't do damage forever (Security).
The industry standard solution to this balancing act is the Access Token and Refresh Token pattern. This guide breaks down what they are, how they work together, and how to use them securely.
1. The Analogy: The Hotel Key Card
The easiest way to understand these tokens is to imagine checking into a hotel.
The ID Check (Authentication): When you first arrive, you show your government ID and credit card to the front desk. This proves who you are.
The Key Card (Access Token): The clerk gives you a plastic key card. This card grants you access to your room, the gym, and the pool.
- Limitation: It expires after a few days. If you lose it, anyone who finds it can enter your room, but only until it expires.
The Reservation (Refresh Token): If you want to extend your stay or get a new key card because yours stopped working, you don't need to show your government ID again. You simply go to the desk, and because they have your valid reservation on file, they issue a fresh key card.
In this scenario:
Access Token = Key Card: Used frequently, opens doors immediately, expires quickly.
Refresh Token = Reservation Record: Used rarely, strictly to get new key cards, lasts a long time.
2. What is an Access Token?
An Access Token is a credential that a client application (like a React website or mobile app) uses to access protected resources on a server.
Format: Usually a JWT (JSON Web Token).
Lifespan: Very short (typically 5 minutes to 1 hour).
Content: It contains "Claims"—data about the user (User ID, Email, Roles, Permissions).
Usage: It is sent in the HTTP Header of every API request:
Authorization: Bearer <access_token>
Why is it short-lived? Since this token is sent over the network frequently and often stored in memory, it is more susceptible to interception (e.g., via XSS attacks). If an attacker steals it, they can only use it for a few minutes before it becomes useless.
3. What is a Refresh Token?
A Refresh Token is a special credential used to obtain a new Access Token.
Format: Usually an opaque string (random characters) or a JWT.
Lifespan: Long (days, weeks, or even months).
Usage: It is never sent to the API endpoints (like
/get-user-profile). It is sent only to a specific auth endpoint (e.g.,/refresh-token).Storage: Because it is powerful, it must be stored more securely than the access token.
Why do we need it? Without a refresh token, once the short-lived access token expired, the user would be logged out and forced to enter their username and password every 15 minutes. The refresh token allows the app to "silently" log the user back in behind the scenes.
4. The Authentication Flow
Here is how the two tokens work in harmony:
Login: The user enters their username and password.
Issue: The server verifies credentials and issues both an Access Token and a Refresh Token.
Access: The client uses the Access Token to request data (e.g., "Get my emails"). The server validates the token and returns the data.
Expiration: Eventually, the Access Token expires. The client tries to use it again, but the API returns a
401 Unauthorizederror.Refresh: The client catches this error and sends the Refresh Token to the auth server's
/refreshendpoint.Renewal: The server checks if the Refresh Token is valid and not blacklisted. If valid, it issues a new Access Token.
Retry: The client replays the original failed request with the new Access Token, and it succeeds.
5. Security Best Practices
Implementing this pattern incorrectly can leave your app vulnerable. Follow these rules:
A. Storage is Critical
Access Tokens: Can be stored in application memory (variables). This means they are lost if the user refreshes the page, but that's okay because the Refresh Token can get a new one.
Refresh Tokens: Do NOT store in LocalStorage. LocalStorage is accessible by any JavaScript running on your page, making it vulnerable to XSS attacks.
- Best Practice: Store the Refresh Token in an HttpOnly, Secure Cookie. This type of cookie cannot be read by JavaScript, preventing XSS theft.
B. Refresh Token Rotation
This is a technique to detect theft.
When a client uses a Refresh Token, the server issues a new Access Token AND a new Refresh Token.
The old Refresh Token is immediately invalidated (deleted from the database).
The Trap: If an attacker stole the old Refresh Token and tries to use it after the legitimate user has already rotated it, the server detects that a "dead" token is being used. The server then concludes that theft has occurred and invalidates the entire family of tokens, forcing the attacker (and the user) to log in again.
C. Revocation
You should have a mechanism to revoke Refresh Tokens.
Use Case: A user clicks "Log out of all devices" or changes their password.
Implementation: Since Refresh Tokens are usually checked against a database or cache (like Redis) on every use, you can simply delete the token from the store to ban the user instantly.