Refresh Token
Authentication
Refresh Token
Get a new access token using refresh token
POST
Refresh Token
Endpoint
http://localhost:3000/api/v1
This endpoint is public but requires a valid refresh token cookie.
Request
No request body is required. The refresh token is automatically sent via HTTP-only cookie.Response
Success Response (200 OK)
string
New JWT access token for authenticating API requests.
Important: Refresh Token Cookie
The server sets a new cookie with these properties:- Name:
refreshToken - HttpOnly: true (cannot be accessed via JavaScript)
- Secure: true (in production, requires HTTPS)
- SameSite: Strict
- Max-Age: 24 hours (86400 seconds)
What Happens on Token Refresh
1
Cookie Validation
System reads refresh token from HTTP-only cookie
2
Token Verification
Validates refresh token signature and expiration
3
Token Type Check
Ensures token type is REFRESH (not ACCESS)
4
User Lookup
Retrieves user from database based on token payload (JobSeeker or Company)
5
Redis Validation
Checks if refresh token ID exists in Redis (not blacklisted/invalidated)
6
Invalidate Old Token
Removes old refresh token from Redis (token rotation security)
7
Generate New Tokens
Creates new access token and refresh token
8
Store New Refresh Token
Stores new refresh token ID in Redis and updates cookie
9
Return Access Token
Returns new access token in response body
Important: Refresh Token Rotation
Security Feature: Each time you refresh, the old refresh token is invalidated and a new one is
issued. This prevents refresh token reuse attacks.
- After calling this endpoint, your old refresh token becomes invalid
- A new refresh token is automatically set as a cookie
- You must use the new refresh token for subsequent refreshes
- Attempting to reuse an old refresh token will fail
Error Responses
401 Unauthorized - Refresh Token Not Found
Returned when refresh token cookie is missing.- User never logged in
- Cookie was cleared/expired
- Request doesn’t include
credentials: 'include' - CORS not configured to allow credentials
401 Unauthorized - Invalid Refresh Token
Returned when refresh token is invalid, expired, or already used.- Token has expired (24 hours passed)
- Token signature is invalid
- Token has been used already (due to rotation)
- Token was manually invalidated/revoked
- User no longer exists in database
- Token not found in Redis (invalidated)
401 Unauthorized - Invalid Token Type
Returned when using access token instead of refresh token.Token Lifecycle
When to Refresh Tokens
On 401 Response (Reactive) - Recommended
On 401 Response (Reactive) - Recommended
Wait until you get a 401 error, then refresh the token and retry the request.Pros:
- Simple implementation
- No unnecessary refreshes
- Works with the examples above
- Brief disruption when token expires
Before Expiration (Proactive)
Before Expiration (Proactive)
Decode the JWT and refresh before it expires (e.g., 5 minutes before). Pros: - Seamless user
experience - No failed requests Cons: - Requires JWT decoding library - Timer management
complexity - May refresh unnecessarily
On App Load (Conservative)
On App Load (Conservative)
Always attempt to refresh on app initialization or page refresh.Pros:
- Ensures fresh token
- Simple to implement
- Extra request on every page load
- May refresh valid tokens
Common Issues
CORS / Cookie Issues
Problem: Refresh token cookie not being sent Solutions:- Ensure
credentials: 'include'is set in fetch - Check CORS settings allow credentials (
Access-Control-Allow-Credentials: true) - Verify cookie domain matches API domain (localhost for local dev)
- Check browser allows third-party cookies (if frontend/backend on different domains)
- In production, ensure frontend and backend are on same domain or properly configured
Token Rotation Confusion
Problem: Old refresh token doesn’t work after refresh This is expected behavior! Token rotation invalidates old tokens after use for security. Solution: Always use the latest refresh token cookie (browser handles this automatically)Infinite Refresh Loop
Problem: App keeps refreshing tokens in a loop Cause: Multiple requests triggering refresh simultaneously without queueing Solution: Implement refresh lock/queue (see TypeScript example above)Lost Cookie After Refresh
Problem: Refresh token cookie disappears after some time Cause: Cookie has 24-hour expiration Solution: This is normal - user needs to login again after 24 hoursSecurity Best Practices
Token Rotation: Old refresh tokens are automatically invalidated when new ones are issued,
preventing replay attacks if a token is intercepted.
Related Endpoints
- Login - Get initial tokens
- Verify Email - Get tokens after email verification
- Register Job Seeker - Create job seeker account
- Register Company - Create company account
