JAVASCRIPT

Secure OAuth Token Refresh Flow in JavaScript

Learn to implement a secure OAuth token refresh mechanism in JavaScript to maintain API access without re-authenticating users, handling token expiration gracefully.

async function refreshTokenAndRetry(originalRequest, accessToken, refreshToken) {
  try {
    const refreshResponse = await fetch('/api/token/refresh', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refreshToken })
    });

    if (!refreshResponse.ok) {
      throw new Error('Failed to refresh token');
    }

    const data = await refreshResponse.json();
    const newAccessToken = data.accessToken;
    
    // Store new access token (e.g., in localStorage, secure cookie, or state)
    localStorage.setItem('accessToken', newAccessToken);
    
    // Retry the original request with the new access token
    originalRequest.headers.set('Authorization', `Bearer ${newAccessToken}`);
    return fetch(originalRequest);

  } catch (error) {
    console.error('Token refresh failed:', error);
    // Redirect to login or handle session expiry
    window.location.href = '/login'; 
    throw error;
  }
}

async function authenticatedFetch(url, options = {}) {
  let accessToken = localStorage.getItem('accessToken');
  const refreshToken = localStorage.getItem('refreshToken'); // Assuming refresh token is also stored

  const headers = new Headers(options.headers || {});
  headers.set('Authorization', `Bearer ${accessToken}`);
  options.headers = headers;

  let response = await fetch(url, options);

  if (response.status === 401 && refreshToken) {
    console.warn('Access token expired. Attempting to refresh...');
    const originalRequest = new Request(url, options);
    response = await refreshTokenAndRetry(originalRequest, accessToken, refreshToken);
  }

  if (!response.ok) {
    // Specific error handling for failed original/retried request
    console.error('API Request failed:', response.status, response.statusText);
  }

  return response;
}

// Example usage:
// authenticatedFetch('https://api.example.com/data')
//   .then(res => res.json())
//   .then(data => console.log(data))
//   .catch(err => console.error(err));
How it works: This snippet provides a robust mechanism to handle expired OAuth access tokens by automatically refreshing them. When an authenticated API call returns a 401 Unauthorized status, it attempts to use a stored refresh token to obtain a new access token from a refresh endpoint. If successful, it retries the original API request with the new token. This ensures a seamless user experience by maintaining their session without requiring re-login, improving the reliability of long-lived API integrations.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs