How to Secure Fetch API in React
Securing the Fetch API in React is crucial for protecting sensitive data, preventing unauthorized API access, and defending your application against common web vulnerabilities. Since React runs entirely in the user’s browser, any code, API keys, or tokens shipped to the client are inherently exposed. This article provides a direct, actionable guide on how to secure your React Fetch requests using environment variables, secure token management, backend proxies, and browser security policies.
1. Never Store Secret API Keys in React
Because React compiles into static assets running in the client browser, anyone can inspect your network tab or source code to find embedded API keys.
- The Risk: Storing secret keys in
.envfiles with theREACT_APP_orVITE_prefix does not hide them; it only injects them into the build files. - The Solution: Use a backend proxy or serverless functions (like AWS Lambda, Next.js API routes, or a simple Node.js Express server). Your React app calls your own backend, and your backend forwards the request to the third-party API using hidden server-side environment variables.
// Instead of calling a third-party API directly with a key:
// fetch('https://api.thirdparty.com/data?key=SECRET_KEY')
// Call your secure backend proxy:
fetch('/api/get-thirdparty-data')
.then(res => res.json())
.then(data => console.log(data));2. Store Authentication Tokens Securely
When using JSON Web Tokens (JWT) for authentication with the Fetch API, how you store the token dictates your application’s security.
- Avoid localStorage and sessionStorage: These storage mechanisms are vulnerable to Cross-Site Scripting (XSS) attacks. If an attacker injects malicious JS into your site, they can easily read these tokens.
- Use HttpOnly Cookies: The most secure way to handle
authentication tokens is by storing them in an
HttpOnlycookie. This cookie cannot be accessed via JavaScript, completely neutralizing the risk of XSS token theft. - Configure Fetch for Cookies: To ensure your Fetch
requests send these secure cookies to your backend, set the
credentialsoption to'include'.
fetch('https://api.yourdomain.com/user/profile', {
method: 'GET',
credentials: 'include' // Sends HttpOnly cookies with the request
})
.then(response => response.json());3. Create a Secured Fetch Wrapper
To prevent repeating authorization logic and to handle token
expiration gracefully, create a centralized, secured fetch wrapper or
custom hook. This wrapper can automatically attach tokens or handle
global error states (like redirecting on a 401 Unauthorized
status).
const secureFetch = async (url, options = {}) => {
const defaultOptions = {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
};
const response = await fetch(url, defaultOptions);
if (response.status === 401) {
// Handle unauthorized access (e.g., redirect to login or refresh token)
console.warn('Unauthorized request. Redirecting...');
}
return response;
};4. Implement Cross-Origin Resource Sharing (CORS)
CORS is a browser-side security mechanism. It does not secure your API from malicious tools like Postman, but it prevents unauthorized third-party websites from making Fetch requests to your backend on behalf of your users.
- Configure your backend API to only accept requests from your React
app’s specific domain (e.g.,
https://www.yourdomain.com). - Avoid using the wildcard
Access-Control-Allow-Origin: *in production environments, especially when handling authenticated requests.
5. Use Content Security Policy (CSP) Headers
A Content Security Policy (CSP) is an added layer of security that helps detect and mitigate certain types of attacks, including XSS and data injection. By configuring a CSP on your web server, you can restrict where your React app is allowed to send Fetch requests.
Specify the connect-src directive in your CSP header to
restrict Fetch API destinations:
Content-Security-Policy: default-src 'self'; connect-src 'self' https://api.yourdomain.com;
This header ensures that even if an attacker manages to inject malicious code into your React application, they cannot send stolen data to an unauthorized external server.