How to Secure REST APIs in React

Securing REST APIs in React applications is crucial for protecting sensitive user data and preventing unauthorized access. While React runs entirely on the client side, robust security requires a combination of secure token storage, proper state management, protected routing, and backend coordination. This article explores the best practices for securing your APIs, including implementing JSON Web Tokens (JWT), safeguarding API keys, handling HTTP-only cookies, and configuring network interceptors.

Store Authentication Tokens Securely

When your React app authenticates with a REST API, it typically receives a JSON Web Token (JWT). How you store this token determines your vulnerability to Cross-Site Scripting (XSS) attacks.

Implement Request Interceptors for Authorization

If your architecture requires passing tokens manually via Authorization headers (e.g., Bearer tokens), use Axios or Fetch interceptors. Interceptors automatically attach the token to every outgoing request without duplicating code.

// Example using Axios Interceptor
axios.interceptors.request.use(
  (config) => {
    const token = getAuthToken(); // Retrieve token from a secure memory state
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

Protect Frontend Routes

While frontend routing cannot replace backend API security, it improves user experience by blocking unauthenticated users from accessing private UI components. Use React Router to build a protected route wrapper.

import { Navigate, Outlet } from 'react-router-dom';

const ProtectedRoute = ({ isAuthenticated }) => {
  return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
};

Ensure that your backend API also validates the token for every request, as a user could easily bypass React-side route guards by manipulating the local application state.

Use a Backend Proxy for API Keys

React applications are compiled and shipped directly to the browser. Any environment variable prefixed with REACT_APP_ or VITE_ is visible in the source code.

To secure sensitive third-party API keys: 1. Create a lightweight backend proxy (e.g., Node.js/Express). 2. Keep your secret API keys on the backend server. 3. Have your React app request data from your own proxy server, which then forwards the request to the third-party API with the hidden key.

Enable Cross-Origin Resource Sharing (CORS)

CORS is a browser security mechanism that restricts resources on a web page from being requested from another domain. Configure your REST API server to only accept requests originating from your React application’s specific domain (e.g., https://myreactapp.com) rather than allowing wildcard access (*).

Implement Content Security Policy (CSP)

A Content Security Policy (CSP) is an HTTP header sent by your server that tells the browser which dynamic resources are allowed to load. Implementing a strict CSP prevents unauthorized scripts from executing in your React application, protecting your API connections from data exfiltration.