What is CSRF protection in Django and how does it work?
Learn how Django CSRF protection works, how the CSRF token and middleware block forged requests, AJAX handling, and common interview mistakes to avoid.
Expected Interview Answer
CSRF (Cross-Site Request Forgery) protection in Django is a security mechanism that stops a malicious site from tricking a logged-in user's browser into submitting unwanted state-changing requests to your application. Django defends against it by requiring a secret, per-session CSRF token on every unsafe request (POST, PUT, PATCH, DELETE).
Django's CsrfViewMiddleware sets a CSRF token in a cookie and expects the same token echoed back in the form data (via the {% csrf_token %} template tag) or in the X-CSRFToken header for AJAX. On each unsafe request the middleware compares the submitted token against the one tied to the user's session, and rejects the request with a 403 if they don't match. Because a foreign attacker's page can read neither the cookie nor the token value (same-origin policy), it cannot forge a valid request.
- Blocks forged state-changing requests from other origins
- Enabled by default via middleware with almost no code
- Works for both classic form posts and AJAX calls
- Ties each token to the user session so stolen tokens don't transfer
- Lets you exempt specific views deliberately with @csrf_exempt
AI Mentor Explanation
Think of the third umpire only accepting a review request when the captain flashes the exact signal card issued to his team before the match. An opposing coach shouting from the stands can imitate the words but never holds that team's specific card, so the review is refused. Django's CSRF token is that private signal card: only a request carrying the token issued to this session is honoured, and forgeries from outsiders are turned away at the boundary.
Step-by-Step Explanation
Step 1
Middleware is enabled
CsrfViewMiddleware sits in the MIDDLEWARE list and intercepts every incoming request.
Step 2
Token is issued
Django generates a masked CSRF token and stores it in a cookie, exposing it to templates and JavaScript.
Step 3
Token is embedded
Forms include {% csrf_token %}, or AJAX code copies the cookie value into the X-CSRFToken request header.
Step 4
Request is validated
On any unsafe method the middleware unmasks and compares the submitted token against the session-bound secret.
Step 5
Decision is made
Matching tokens let the view run; a missing or wrong token returns a 403 Forbidden before the view executes.
What Interviewer Expects
- Clear definition of CSRF as a cross-origin forgery attack
- Knowledge that CsrfViewMiddleware and the token drive the defense
- Difference between the {% csrf_token %} tag and the X-CSRFToken header
- Awareness that only unsafe HTTP methods are checked
- When and why to use @csrf_exempt and its risks
Common Mistakes
- Confusing CSRF with XSS — they are different attack classes
- Sprinkling @csrf_exempt on views to silence 403 errors
- Forgetting to send the X-CSRFToken header in AJAX requests
- Believing GET requests are CSRF-protected (only unsafe methods are checked)
- Assuming the token alone stops session hijacking
Best Answer (HR Friendly)
“CSRF protection stops a shady website from secretly making your logged-in browser perform actions you never intended, like changing your password. Django hands each user a secret token and only trusts requests that carry it, so forged requests from other sites get rejected automatically.”
Code Example
<!-- template: token added to the form -->
<form method="post">
{% csrf_token %}
<input name="email">
<button>Save</button>
</form>
<script>
// AJAX: read the cookie and send it back as a header
function getCookie(name) {
const m = document.cookie.match('(^|;)\\s*' + name + '=([^;]+)');
return m ? m.pop() : '';
}
fetch('/profile/update/', {
method: 'POST',
headers: { 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({ email: '[email protected]' })
});
</script>Follow-up Questions
- How is CSRF different from XSS?
- Why does Django not check CSRF tokens on GET requests?
- When is @csrf_exempt appropriate and what are the dangers?
- How do you handle CSRF tokens in a decoupled SPA or mobile client?
- What does the CSRF_COOKIE_HTTPONLY setting change?
MCQ Practice
1. Which Django component enforces CSRF protection by default?
CsrfViewMiddleware issues and validates the CSRF token on unsafe requests; it is enabled by default in the MIDDLEWARE list.
2. For which HTTP methods does Django perform CSRF validation?
Safe methods (GET, HEAD, OPTIONS, TRACE) are assumed not to change state, so Django only validates the token on unsafe methods.
3. How should an AJAX request supply the CSRF token?
AJAX clients read the csrftoken cookie and send it back in the X-CSRFToken header, which the middleware validates.
Flash Cards
What attack does Django's CSRF protection stop? — Cross-Site Request Forgery — a foreign site tricking a logged-in browser into state-changing requests.
Where does Django store the CSRF token? — In a cookie (csrftoken), which templates and JavaScript read to echo it back.
How do you add the token to a form? — Place the {% csrf_token %} template tag inside the <form> element.
What happens on a token mismatch? — CsrfViewMiddleware returns a 403 Forbidden before the view runs.