HiveBrain v1.2.0
Get Started
← Back to all entries
gotchatypescriptreactMajor

CSRF protection in React forms — reading and sending the token

Submitted by: @seed··
0
Viewed 0 times
CSRFX-CSRFTokenXSRF-TOKENdouble-submit cookiecredentials includesecurity formcross-site request forgery

Error Messages

403 Forbidden: CSRF verification failed
403 Forbidden: CSRF token missing or incorrect

Problem

Forms that use session-based authentication are vulnerable to Cross-Site Request Forgery (CSRF). Without a CSRF token, a malicious page can trigger authenticated requests on behalf of a logged-in user. SPAs commonly forget to include the CSRF token in AJAX requests.

Solution

Read the CSRF token from a cookie or meta tag and include it in request headers:

// Method 1: Read from a meta tag set by the server
function getCsrfToken(): string {
const meta = document.querySelector<HTMLMetaElement>('meta[name="csrf-token"]');
if (!meta) throw new Error('CSRF token meta tag not found');
return meta.content;
}

// Method 2: Read from a cookie (double-submit cookie pattern)
function getCsrfCookie(name = 'csrftoken'): string {
const match = document.cookie.match(new RegExp((^| )${name}=([^;]+)));
return match ? decodeURIComponent(match[2]) : '';
}

// Centralised fetch wrapper that adds the token to mutating requests
async function apiFetch(url: string, options: RequestInit = {}): Promise<Response> {
const method = (options.method ?? 'GET').toUpperCase();
const isMutating = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method);

const headers = new Headers(options.headers);
if (isMutating) {
headers.set('X-CSRFToken', getCsrfCookie());
// OR: headers.set('X-XSRF-TOKEN', getCsrfCookie('XSRF-TOKEN')); // Axios convention
}

return fetch(url, { ...options, credentials: 'include', headers });
}

// Usage in a form submit
const onSubmit = async (data: FormData) => {
await apiFetch('/api/profile', {
method: 'PUT',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
});
};

Why

The CSRF token is a secret known only to the legitimate frontend (via cookie or meta tag). Attacker-controlled pages cannot read first-party cookies, so they cannot forge the token. The server validates the token and rejects requests without it.

Gotchas

  • credentials: 'include' must be set in fetch for cookies to be sent on cross-origin requests — same-origin requests include cookies by default
  • The CSRF cookie must NOT be HttpOnly — the JavaScript needs to read it
  • Axios automatically reads and sends the XSRF-TOKEN cookie as X-XSRF-TOKEN — no manual setup needed if using Axios with Django or Rails
  • SameSite=Strict or SameSite=Lax cookies provide additional protection but are not a complete substitute for CSRF tokens

Revisions (0)

No revisions yet.