Refresh Token - sonuprajapati15/Authentication-Authorization GitHub Wiki

Authentication Token Expiry & Refresh Strategy

1. Introduction

This document provides a solution for handling authentication token expiration and refresh without requiring the user to log in again. It describes two approaches:

  1. Client-Managed Token Refresh
  2. Backend-Managed Token Refresh

The document also includes High-Level Design (HLD), Low-Level Design (LLD), and Architecture Diagrams.

refrsh_token

2. High-Level Design (HLD)

Problem Statement

  • Access tokens expire after a fixed duration (e.g., 30 minutes).
  • Users should not have to log in again if they are active before the refresh token expires.
  • Ensure security while minimizing latency.

Solution Overview

  • Access Token (Short-lived, e.g., 15-30 mins) - Used for API authentication.
  • Refresh Token (Long-lived, e.g., 30 days) - Used to obtain a new access token when it expires.
  • Two strategies:
    • Client-Managed Refresh: The client checks token expiry and refreshes before making API requests.
    • Backend-Managed Refresh: The backend handles token refresh before responding to the client.

Architecture Diagram

graph TD;
    User -->|Login| AuthServer;
    AuthServer -->|Generate Access & Refresh Token| User;
    User -->|Send Access Token| API;
    API -->|Validate Token| AuthServer;
    AuthServer -->|Token Expired?| CheckExpiration;
    CheckExpiration -->|Yes| RefreshToken;
    RefreshToken -->|Return New Access Token| API;
    API -->|Serve Request| User;

3. Low-Level Design (LLD)

3.1 Client-Managed Token Refresh

Flow

  1. Client stores access and refresh tokens securely.
  2. Before making an API call, the client checks if the access token is expired.
  3. If expired, the client requests a new access token using the refresh token.
  4. The client updates the stored token and proceeds with the request.

Implementation (React + Axios)

import axios from 'axios';

const api = axios.create({ baseURL: 'https://your-api.com', withCredentials: true, });

api.interceptors.request.use(async (config) => { let accessToken = localStorage.getItem('accessToken');

if (isTokenExpired(accessToken)) { accessToken = await refreshToken(); }

config.headers.Authorization = Bearer ${accessToken}; return config; }, (error) => Promise.reject(error));

async function refreshToken() { try { const response = await axios.post('https://your-api.com/refresh-token', {}, { withCredentials: true }); localStorage.setItem('accessToken', response.data.accessToken); return response.data.accessToken; } catch (error) { console.error('Session expired. Please log in again.'); } }


3.2 Backend-Managed Token Refresh

Flow

  1. Client sends an API request with the access token.
  2. Backend validates the token.
  3. If expired, backend uses the refresh token (stored in HttpOnly cookies) to generate a new access token.
  4. Backend responds with a new access token.

Implementation (Node.js + Express)

app.use(async (req, res, next) => {
  let accessToken = req.headers.authorization?.split(" ")[1];
  if (!accessToken) return res.sendStatus(401);

try { jwt.verify(accessToken, ACCESS_SECRET); return next(); } catch (err) { if (err.name === 'TokenExpiredError') { const refreshToken = req.cookies.refreshToken; if (!refreshToken) return res.sendStatus(403);

  try {
    const payload = jwt.verify(refreshToken, REFRESH_SECRET);
    const newAccessToken = jwt.sign({ userId: payload.userId }, ACCESS_SECRET, { expiresIn: '15m' });
    res.setHeader('Authorization', `Bearer ${newAccessToken}`);
    req.headers.authorization = `Bearer ${newAccessToken}`;
    return next();
  } catch (refreshErr) {
    return res.sendStatus(403);
  }
} else {
  return res.sendStatus(401);
}

} });


4. Comparison of Strategies

Feature Client-Managed Refresh Backend-Managed Refresh
Security Moderate (client storage) High (server-controlled)
Performance Faster Slightly slower (extra backend processing)
Backend Load Lower Higher
Works for APIs Requires client logic Fully managed by server

5. Conclusion

  • Use Client-Managed Refresh for frontend-heavy applications.
  • Use Backend-Managed Refresh for secure API-driven applications.
  • Always store refresh tokens securely using HttpOnly cookies.

6. Future Enhancements

  • Implement token revocation for better security.
  • Use OAuth 2.0 with PKCE for enhanced security.
  • Implement rate limiting to prevent abuse of refresh token endpoints.
⚠️ **GitHub.com Fallback** ⚠️