Skip to main content
POST
Refresh Token

Endpoint

Base URL: 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.
Important: You must include credentials: 'include' in your fetch request to send the refresh token cookie.

Response

Success Response (200 OK)

string
New JWT access token for authenticating API requests.
The refresh token is sent via HTTP-only cookie and is not included in the response body. A new refresh token cookie is automatically set with each refresh.
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.
What this means:
  • 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.
Possible causes:
  • User never logged in
  • Cookie was cleared/expired
  • Request doesn’t include credentials: 'include'
  • CORS not configured to allow credentials
Solution: User needs to login again.

401 Unauthorized - Invalid Refresh Token

Returned when refresh token is invalid, expired, or already used.
Possible causes:
  • 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)
Solution: Redirect user to login page.

401 Unauthorized - Invalid Token Type

Returned when using access token instead of refresh token.
Cause: Trying to use an access token with this endpoint. This endpoint requires a refresh token. Solution: Ensure you’re sending the refresh token cookie, not the access token.

Token Lifecycle

When to Refresh Tokens

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
Always attempt to refresh on app initialization or page refresh.Pros:
  • Ensures fresh token
  • Simple to implement
Cons:
  • Extra request on every page load
  • May refresh valid tokens

Common 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) 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 hours

Security Best Practices

Never store refresh tokens in localStorage or sessionStorage. They’re automatically handled via HTTP-only cookies which cannot be accessed by JavaScript (protecting against XSS attacks).
Token Rotation: Old refresh tokens are automatically invalidated when new ones are issued, preventing replay attacks if a token is intercepted.
Silent Refresh: Implement automatic token refresh in the background for seamless user experience without interrupting their workflow.