How to Secure Axios in React

Securing data transmission and API communication is a critical aspect of developing robust React applications. This article provides a straightforward guide on how to secure the Axios library in React, focusing on essential security practices including environment variable management, Axios interceptors for token handling, built-in Cross-Site Request Forgery (CSRF) protection, and secure error handling.

1. Use Environment Variables for API Configurations

Never hardcode your API base URLs, API keys, or sensitive endpoints directly into your React components. Instead, store them in environment variables.

For projects built with Vite, use the VITE_ prefix:

VITE_API_BASE_URL=https://api.yourdomain.com

For projects built with Create React App, use the REACT_APP_ prefix:

REACT_APP_API_BASE_URL=https://api.yourdomain.com

In your Axios configuration, reference the environment variable securely:

import axios from 'axios';

const api = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL, // Vite configuration
});

2. Secure Token Management Using Interceptors

To authenticate requests, you should attach authorization tokens (like JWTs) to your API calls. Axios interceptors allow you to dynamically inject these tokens into the request headers right before they are sent, ensuring you do not manually pass credentials in every single component.

api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token'); // Or a secure state management store
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

Note: For optimal security against XSS attacks, store sensitive tokens in HttpOnly cookies rather than localStorage. If using HttpOnly cookies, set withCredentials: true in your Axios configuration.

3. Enable CSRF (Cross-Site Request Forgery) Protection

Axios has built-in support for CSRF protection. It can automatically read a CSRF token from a cookie and include it in your request headers. You can configure this when creating your Axios instance:

const api = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  xsrfCookieName: 'XSRF-TOKEN', // Name of the cookie containing the token
  xsrfHeaderName: 'X-XSRF-TOKEN', // Name of the header the server expects
  withCredentials: true, // Ensures cookies are sent with cross-origin requests
});

4. Secure Response Handling and Error Masking

Exposing raw database errors or system stack traces to the end-user poses a significant security risk. Use Axios response interceptors to catch errors globally and sanitize the information displayed to the client.

api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response) {
      // Handle known HTTP status codes globally
      if (error.response.status === 401) {
        // Redirect to login or refresh token
      }
      // Mask internal server errors
      if (error.response.status === 500) {
        error.message = "A system error occurred. Please try again later.";
      }
    }
    return Promise.reject(error);
  }
);

5. Enforce HTTPS and Modern TLS

Ensure that your baseURL always specifies the https:// protocol. This guarantees that all communication between your React application and the backend API is encrypted in transit, preventing man-in-the-middle (MITM) attacks and credential eavesdropping.