Open In App

CSRF token in Django

Last Updated : 26 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Django provides a feature known as a CSRF token to get away from CSRF attacks that can be very dangerous. when the session of the user starts on a website, a token is generated which is then cross-verified with the token present with the request whenever a request is being processed.

What is a CSRF?

CSRF means cross-site request forgery. In this type of attack, the attacker sends a link in the form of sms, email, or chat. In this way, the attacker tricks the user who is already authenticated on the website to perform various actions such as transfer of funds, change of email, and so on. Depending upon the nature of the attack the attacker may take full access to the account.

Syntax of CSRF Token in Django

 {% csrf_token %} 

What is CSRF Token in Django?

Django provides a feature to prevent such types of malicious attacks. When a user is authenticated and surfing on the website, Django generates a unique CSRF token for each session. This token is included in forms or requests sent by the user and is checked by the server to verify that the request is coming from the authenticated user and not from a malicious source.

While CSRF protection primarily focuses on protecting against actions that make changes in data, it’s still a good practice to include CSRF tokens in forms generated by Django, even for GET requests. This can help prevent attackers from creating malicious forms that trick users into making unwanted changes.

Working of CSRF Protection

To understand this let us take an example. Suppose you are logged into the website. The attacker sends a link with the help of an email, chat, or with the use of sms. The link contains the request which the attacker wants to be performed. As the user is already authenticated on the website the request is completed when he clicks on the link. This type of request is very dangerous as it may take complete access to the data and other harmful actions may be performed such as transfer of funds, change of email and so on.

Token Generation

When a user logs in or starts a session, Django generates a random and unique CSRF token for that session. This token is usually a long string of characters. This token is associated with the user’s session and stored on the server.

CsrfViewMiddleware sends this cookie with the response whenever  django.middleware.csrf.get_token() is called. It can also send it in other cases. For security reasons, the value of the secret is changed each time a user logs in.

Token Inclusion in Forms

When Django renders an HTML form using a template, it includes the CSRF token using the {% csrf_token %} template tag. The CSRF token should be added as a hidden input field in the form.

Example

HTML




<form method="post">
    {% csrf_token %}
    <!-- Other form fields here -->
    <button type="submit">Submit</button>
</form>


Token Validation on Submission

When the user submits the form, the CSRF token is sent along with the request, either as a POST parameter or a request header (e.g., X-CSRFToken). The token is extracted from the request by the server. It is then verified that if this token (received in request) matches with the token which is linked with the user’s session. If the token matches, the request is considered as valid and we can proceed with it. If they don’t match, then the server interprets it as it may be a CSRF attack and rejects the request.

How to Use Django’s CSRF Middleware?

We need to add django.middleware.csrf.CsrfViewMiddleware in the settings.py file to enable it. By default, Django already has this enabled, as in the following example:

Screenshot-2023-08-18-155432

CSRF Middleware

Let us create HTML page in which usersubmits a form. We have included the {%csrf_token%} as a hidden field in our HTML code.

HTML file

HTML




<form method="post">
    {% csrf_token %}
    <form action="/your-name/" method="post">
    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
    <button type="submit">Submit</button>
</form>


The CSRF Decorator Method

When we want that our CSRF should work only for particular view then we can use Decorator method in which have to place ‘@csrf_protect’ at the top of that function as shown below in the views.py file

Views.py

Python3




from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect
 
@csrf_protect
def simulate_csrf_error(request):
    if request.method == 'POST':
        return HttpResponse("Form submitted successfully!")
    return HttpResponse("GET request, please submit the form.")


How Does the CSRF Token Work?

Now suppose a user who is already authenticated on the website tries to submit the form , the request is easily processed and the data is submitted. Now suppose an attacker sends an link to the authenticated user to submit a information as in this case the csrf token will not match with the token generated for the user at the starting of the session, so it will throw a error 403 as shown below.

imgonline-com-ua-resize-owKbqrMEcQ9Sn8

csrf token mismatch error in django

In this way csrf_token in django helps in preventing attacks from malicious attackers.

Using CSRF protection with AJAX

When making AJAX or API requests from JavaScript, we need to manually include the CSRF token in the request headers.

Assume that we have a page where we want to send data to a Django API endpoint using AJAX. We need to include the CSRF token as a header in our AJAX request. We can acquire the token as shown in the below example:

The JavaScript code in the HTML page extracts the CSRF token from the cookie using the getCookie function and sends a POST request to the Django API endpoint.

HTML




<!DOCTYPE html>
<html>
<head>
    <title>API Request Example</title>
    <script>
        // Function to get the CSRF token from the cookie
        function getCookie(name) {
            const value = `; ${document.cookie}`;
            const parts = value.split(`; ${name}=`);
            if (parts.length === 2) return parts.pop().split(';').shift();
        }
 
        // Function to send a POST request with CSRF token
        function sendPostRequest() {
            const csrfToken = getCookie('csrftoken');
            const url = '/api/some_endpoint/';
 
            const data = { key: 'value' };
 
            fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': csrfToken // Include the CSRF token in the header
                },
                body: JSON.stringify(data)
            })
            .then(response => response.json())
            .then(data => {
                console.log('Response from server:', data);
            })
            .catch(error => {
                console.error('Error:', error);
            });
        }
    </script>
</head>
<body>
    <button onclick="sendPostRequest()">Send POST Request</button>
</body>
</html>


Another way to use CSRF protection in Jinja2 Templates

Django’s Jinja2 template backend adds {{ csrf_input }} to the context of all templates which acts same as  {% csrf_token %} in the Django template language. For example:

HTML




<form method="post">{{ csrf_input }}




Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads