CSRF Protection0%

CSRF Protection

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

CSRF Protection

Cross-Site Request Forgery (CSRF) is a critical web security vulnerability where a malicious third-party site tricks an authenticated user's browser into executing unauthorized mutations (e.g. changing passwords, transferring funds, or updating records) on a trusted application. Django includes an industry-leading, built-in CSRF defense framework.


1. How CSRF Attacks Work

Output
1. User logs into https://bank.enterprise.com (Session cookie is set in browser)
2. In another tab, user visits https://malicious-site.com
3. Malicious site automatically submits hidden form:
<form action="https://bank.enterprise.com/transfer" method="POST">
<input name="amount" value="5000" />
<input name="to_account" value="attacker_id" />
</form>
4. Browser automatically attaches bank.enterprise.com cookies!
5. Without CSRF tokens: Bank executes unauthorized transfer!

2. Django's Defense: Synchronizer Token Pattern

Django stops CSRF using cryptographically secure Synchronizer Tokens:

  • The server generates a unique secret token bound to the user's session or cookie.
  • Every mutating HTML form must embed this token.
  • CsrfViewMiddleware verifies that the submitted token matches the secret cookie. An attacker on an external domain cannot read or forge the token!

In HTML Templates:

Every <form method="POST"> must include {% csrf_token %}:

DJANGO
<form method="POST" action="{% url 'articles:create' %}">
{% csrf_token %} {# Injects hidden <input type="hidden" name="csrfmiddlewaretoken" value="..." /> #}
<input type="text" name="title" required />
<button type="submit">Publish</button>
</form>

If the token is missing or invalid on a POST request, Django immediately aborts and returns 403 Forbidden (CSRF verification failed).


3. Handling CSRF in AJAX & SPA Frontends (React / Axios)

Single Page Applications (React, Vue) sending JSON requests (application/json) cannot use HTML form inputs. Instead, Django places the CSRF token in a readable cookie (csrftoken), which the frontend sends in the X-CSRFToken HTTP header:

Python
# config/settings.py
# Set cookie to be accessible by client JavaScript for AJAX/React:
CSRF_COOKIE_HTTPONLY = False
CSRF_COOKIE_SAMESITE = "Lax"

In React / Axios:

TypeScript
import axios from "axios";
 
// Helper to extract cookie value
function getCookie(name: string): string | null {
const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
return match ? decodeURIComponent(match[2]) : null;
}
 
// Global Axios configuration: automatically attaches Django CSRF token
axios.interceptors.request.use((config) => {
const csrfToken = getCookie("csrftoken");
if (csrfToken && config.headers) {
config.headers["X-CSRFToken"] = csrfToken;
}
return config;
});

4. Exempting Webhooks with @csrf_exempt

External incoming webhooks (e.g. Stripe, GitHub, Twilio) originate from third-party servers that do not possess browser sessions or CSRF tokens. Exempt these specific endpoints defensively:

Python
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
 
@csrf_exempt
def stripe_webhook_view(request):
# Verify cryptographic signature using Stripe SDK instead of CSRF!
...

Interactive Quiz

Practice Quiz

Question 1
What does the {% csrf_token %} template tag render inside an HTML <form>?
Question 2
Why does an attacker's website fail to send a valid CSRF token on behalf of a victim?
Question 3
Which HTTP header does Django inspect when receiving AJAX / React POST requests containing a CSRF token?
Question 4
When is it safe and acceptable to use the @csrf_exempt decorator?
Question 5
What setting determines whether the CSRF cookie can be read by JavaScript via document.cookie?
Next Lesson

Security Best Practices

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext