axios-auth-refresh

repository·master·Indexed 22 days ago

https://github.com/flyrell/axios-auth-refresh

An Axios plugin (v5.0.2) that automates the process of refreshing authorization tokens when requests fail due to unauthorized status codes. It uses Axios interceptors to execute custom refresh logic, manages request queuing to prevent multiple simultaneous refresh calls, and ensures retried requests use updated credentials. Key features include configurable status codes, request deduplication, and the ability to skip the interceptor for specific requests using the skipAuthRefresh flag.

Tokens
2.5K
Snippets
8
Records
11
Agent score
75%

What's inside axios-auth-refresh

  1. How axios-auth-refresh works

    master

    The library uses Axios interceptors to watch for specific failure status codes (defaulting to 401 Unauthorized). When a failure occurs, it executes a provided refreshAuthLogic function.

    Key behaviors:

    • Request Stalling: While the refresh logic is running, any additional incoming requests are automatically stalled (queued).
    • Automatic Resolution: Once the refresh logic resolves, the stalled requests are retried with the updated configuration. If the refresh logic fails, the stalled requests are rejected.
    • Deduplication: By default, only one refresh cycle runs at a time, even if multiple requests fail simultaneously. This prevents multiple redundant refresh calls.
    import axios from 'axios';
    import { createAuthRefresh } from 'axios-auth-refresh';
    
    // Function that will be called to refresh authorization
    const refreshAuthLogic = (failedRequest) =>
        axios.post('https://www.example.com/auth/token/refresh').then((tokenRefreshResponse) => {
            localStorage.setItem('token', tokenRefreshResponse.data.token);
            failedRequest.response.config.headers['Authorization'] = 'Bearer ' + tokenRefreshResponse.data.token;
            return Promise.resolve();
        });
    
    // Instantiate the interceptor
    createAuthRefresh(axios, refreshAuthLogic);
  2. Best practice: Use a request interceptor for tokens

    master

    Because the library stalls requests while refreshing, it is recommended to use a standard Axios request interceptor to inject the latest token from your storage. This ensures that when a stalled request is finally released, it uses the most current token.

    // Obtain the fresh token each time the function is called
    function getAccessToken() {
        return localStorage.getItem('token');
    }
    
    // Use interceptor to inject the token to requests
    axios.interceptors.request.use((request) => {
        request.headers['Authorization'] = `Bearer ${getAccessToken()}`;
        return request;
    });
  3. Skip the interceptor for specific requests

    master

    You can prevent the interceptor from acting on a specific request by passing skipAuthRefresh: true in the request configuration.

    If using TypeScript, import AxiosAuthRefreshRequestConfig to ensure type safety.

    // JavaScript
    axios.get('https://www.example.com/', { skipAuthRefresh: true });
    
    // TypeScript
    import { AxiosAuthRefreshRequestConfig } from 'axios-auth-refresh';
  4. Configure axios-auth-refresh options

    master

    The options object in createAuthRefresh allows you to customize the interceptor behavior:

    • statusCodes: Array of status codes that trigger a refresh. Default: [401].
    • shouldRefresh: A function (error) => boolean to determine if a request should trigger a refresh. If provided, statusCodes is ignored.
    • retryInstance: The Axios instance used to retry stalled requests. Defaults to the instance passed to createAuthRefresh.
    • onRetry: A callback (requestConfig) => requestConfig called before a stalled request is retried. Use this to mutate the config (e.g., changing baseURL).
    • deduplicateRefresh: Boolean. If false, every failed request triggers its own refresh cycle. Warning: If disabled, you must use skipAuthRefresh on your refresh calls to avoid infinite loops.
    • interceptNetworkError: Boolean. If true, intercepts network errors (e.g., CORS issues where status codes aren't readable). Use as a last resort.
  5. Use createAuthRefresh to implement automatic refresh

    master

    To activate the interceptors, call createAuthRefresh with your Axios instance and a refresh logic function. The refresh function must return a promise and accepts one parameter: the failedRequest object.

    createAuthRefresh(
        axios: AxiosInstance,
        refreshAuthLogic: (failedRequest: any) => Promise<any>,
        options: AxiosAuthRefreshOptions = {}
    ): number;
  6. Configure createAuthRefresh options

    master

    The createAuthRefresh function accepts an optional AxiosAuthRefreshOptions object to customize interceptor behavior.

    Key behaviors controlled by options include:

    • statusCodes: Defines which error response status codes should trigger the refresh logic.
    • maxRetries: The maximum number of times a single request will be retried after a refresh attempt before being rejected.
    • deduplicateRefresh: When enabled, prevents multiple simultaneous refresh calls if they are made on the same instance.
    • skipAuthRefresh: (Used on individual request configs) A flag to manually skip the refresh interceptor for specific requests.
  7. Configure axios-auth-refresh with AxiosAuthRefreshOptions

    master

    When initializing the refresh interceptor, you can provide an AxiosAuthRefreshOptions object to customize the refresh behavior. Key options include:

    • statusCodes: An array of HTTP status codes that should trigger a token refresh (e.g., [401, 403]).
    • shouldRefresh: A function (error: AxiosError) => boolean that allows custom logic to decide if a refresh should occur. If this is provided, the statusCodes logic is ignored.
    • retryInstance: An optional AxiosInstance to use specifically for the retry attempts.
    • interceptNetworkError: A boolean to determine if network errors should also trigger a refresh.
    • deduplicateRefresh: A boolean to prevent multiple simultaneous refresh calls.
    • onRetry: A function (requestConfig: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig> used to modify the request configuration before the retry is executed.
    • maxRetries: The maximum number of consecutive refresh attempts allowed before giving up. This prevents infinite loops if the retried request continues to fail with auth errors. Defaults to 3.
    const options: AxiosAuthRefreshOptions = {
      statusCodes: [401],
      maxRetries: 3,
      shouldRefresh: (error) => error.response?.status === 401,
      onRetry: (config) => {
        // Modify config before retry
        return config;
      }
    };
  8. Initialize authentication refresh with createAuthRefresh()

    master

    Use createAuthRefresh to attach an interceptor to an AxiosInstance that automatically handles token refresh logic when specific error status codes are encountered.

    When a qualifying error occurs:

    1. The provided refreshAuthCall is executed.
    2. While the refresh call is in progress, all subsequent requests made to the same instance are queued.
    3. Once the refresh call resolves, the original failed request is retried using a retry instance.
    4. If the refresh call fails, the error is rejected.

    Loop Protection: The interceptor tracks retries via a __authRefreshRetryCount property on the request config. If the number of retries exceeds options.maxRetries, the request is rejected to prevent infinite loops.

    Instance Pausing: By default, while a refresh is running, the instance is marked as 'paused' to prevent the interceptor from intercepting the refresh call itself. This prevents infinite loops without requiring manual flagging of requests.

    import axios from 'axios';
    import { createAuthRefresh } from 'axios-auth-refresh';
    
    const instance = axios.create();
    
    const refreshAuthCall = async (error: any) => {
      // Your logic to call the refresh token endpoint
      const response = await axios.post('/refresh-token');
      // Update your credentials/headers here
      return response.data;
    };
    
    // Returns an interceptor ID that can be used to eject the interceptor
    const interceptorId = createAuthRefresh(instance, refreshAuthCall, { 
      // optional configuration
    });
  9. Skip auth refresh for specific requests using skipAuthRefresh

    master

    You can bypass the automatic token refresh logic for a single request by adding the skipAuthRefresh property to the AxiosRequestConfig object passed to an Axios request.

    axios.get('/api/public-data', {
      skipAuthRefresh: true
    });
  10. Types for axios-auth-refresh

    master

    The library exports the following types for configuration and type safety:

    • AxiosAuthRefreshOptions: The configuration object passed to createAuthRefresh.
    • AxiosAuthRefreshRequestConfig: Configuration properties that can be attached to individual Axios request objects.