Skip to main content

How to resolve Forbidden(403) if Djangos CSRF mechanism has not been used in POST method

Are you a newbie to Django like me. ?

if yes , you would have come across "Forbidden (403)" when you are using forms or when you have used ajax post method to your app view and have not used CSRF mechanism properly. Below are ways I have resolved the 403 issue. Even before we see how CSRF should be used , we will see what CSRF is actually for.

Cross Site Request Forgery protection

" The CSRF middleware and template tag provides easy-to-use protection against Cross Site Request Forgeries. This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser. A related type of attack, ‘login CSRF’, where an attacking site tricks a user’s browser into logging into a site with someone else’s credentials, is also covered." 

CSRF middleware is enabled in your project settings.py file like below

CSRF middleware enabled

Alternatively , If this is not enabled or set , you can still use the protection by decorating your views with csrf_protect

csrf_protect in views.py


Ok now we have csrf protection on our views. Let us see how we can use it.
Using the csrf middleware token. Csrf middle ware token looks something like this below
S4HZCPE6sdPSP7r4b9TME2NPb4pfsNhV53cclwaFIEqOfCZXe8lwQ3PDqZhE7QJq

csrf token in browser

   1. FORM

We have to use  the csrf_token tag inside the <form> element if the form .for internal url
<form method="post">{% csrf_token %}
csrf_token in form tag

2. IN AJAX

First, we need to get the crsf cookie and this depends on whether CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are False or True
   i) If CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are False

You can get the cookie by using below function as in django documentation
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
const csrftoken = getCookie('csrftoken');
Now the cookie is stored in csrf token variable which can be used later in your ajax post.
Alternatively you can also use the CND javascript library

  <script src="https://cdn.jsdelivr.net/npm/js-cookie@rc/dist/js.cookie.min.js"></script>

using js.cookie CDN

You can then use the library method Cookies.get() to get cookie.
const csrftoken = Cookies.get('csrftoken');
ii) If CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are True
You can simply use jquery to get the cookie value like below
{% csrf_token %}
<script type="text/javascript">
// using jQuery
const csrftoken = $ ("[name=csrfmiddlewaretoken]").val();
</script>
Secondly .now that we have the csrf token available , we can simply specify in our ajax post method. In my example i have used jquery post method.
csrfmiddlewaretoken in ajax

Now when we used the post method , there should be no forbidden (403) error. 
Hope this helps.!!

Comments

Popular posts from this blog

How to expose your multiple database for admin site in django

Assuming you have multiple databases in your django project for different apps. Now you realize that when you save or do other operations in admin site for your app model , you realize that values are save to default database from project. Below we will see simple steps to make admin site of django to use your other database configured for the app instead of default. Now your multiple database in settings.py may looks something like this settings.py So inorder to inform the django admin site use your intendended database for your app. Navigate to your app in the django project and open your admin.py. Below example shows model names ProfileSection which when the user saves the information in admin site uses default database. admin.py If you want to provide an admin interface for a model on a database other than that specified by your router chain, you’ll need to write custom ModelAdmin classes that will direct the admin to use a specific database for content.  https://docs.djangoprojec