How to Use Refresh Token in REST API for Secure Authentication
In a REST API, use a
refresh token to get a new access token when the old one expires without asking the user to log in again. The client sends the refresh token to a dedicated endpoint, which verifies it and returns a fresh access token for continued access.Syntax
The typical flow involves these parts:
- Refresh Token: A long-lived token stored securely by the client.
- Access Token: A short-lived token used to access protected API endpoints.
- Refresh Endpoint: An API route where the client sends the refresh token to get a new access token.
Example request to refresh token endpoint:
POST /auth/refresh
Headers: Content-Type: application/json
Body: { "refresh_token": "your_refresh_token_here" }
http
POST /auth/refresh HTTP/1.1 Host: api.example.com Content-Type: application/json { "refresh_token": "your_refresh_token_here" }
Example
This example shows a simple Node.js Express server handling refresh tokens. The client sends a refresh token to /auth/refresh. The server verifies it and returns a new access token.
javascript
import express from 'express'; import jwt from 'jsonwebtoken'; const app = express(); app.use(express.json()); const ACCESS_TOKEN_SECRET = 'access-secret'; const REFRESH_TOKEN_SECRET = 'refresh-secret'; // In-memory store for refresh tokens (for demo only) let refreshTokens = []; // Endpoint to refresh access token app.post('/auth/refresh', (req, res) => { const { refresh_token } = req.body; if (!refresh_token) return res.status(401).json({ message: 'Refresh token required' }); if (!refreshTokens.includes(refresh_token)) return res.status(403).json({ message: 'Invalid refresh token' }); jwt.verify(refresh_token, REFRESH_TOKEN_SECRET, (err, user) => { if (err) return res.status(403).json({ message: 'Invalid refresh token' }); const accessToken = jwt.sign({ username: user.username }, ACCESS_TOKEN_SECRET, { expiresIn: '15m' }); res.json({ accessToken }); }); }); // Start server app.listen(3000, () => console.log('Server running on http://localhost:3000'));
Output
Server running on http://localhost:3000
Common Pitfalls
- Not storing refresh tokens securely: Refresh tokens should be stored safely (e.g., httpOnly cookies) to prevent theft.
- Not validating refresh tokens: Always verify the refresh token's signature and expiration before issuing a new access token.
- Not revoking refresh tokens: Implement a way to revoke refresh tokens on logout or suspicious activity.
- Using refresh tokens as access tokens: Never use refresh tokens to access protected resources directly.
javascript
/* Wrong: Using refresh token as access token */ fetch('/protected/data', { headers: { Authorization: `Bearer ${refreshToken}` } }); /* Right: Use access token for API calls, refresh token only to get new access tokens */ fetch('/protected/data', { headers: { Authorization: `Bearer ${accessToken}` } });
Quick Reference
| Step | Description |
|---|---|
| 1. Issue Tokens | Send access and refresh tokens after user login. |
| 2. Use Access Token | Client uses access token to call protected APIs. |
| 3. Detect Expiry | When access token expires, client calls refresh endpoint. |
| 4. Refresh Token | Client sends refresh token to get new access token. |
| 5. Validate & Respond | Server verifies refresh token and returns new access token. |
| 6. Repeat | Client repeats steps 2-5 until refresh token expires or is revoked. |
Key Takeaways
Use refresh tokens to get new access tokens without forcing user login again.
Always verify refresh tokens on the server before issuing new access tokens.
Store refresh tokens securely to prevent unauthorized use.
Do not use refresh tokens to access protected API endpoints directly.
Implement refresh token revocation to protect user sessions.