0

I have a django application that is successfully able to signup and login a user.However I am unable to logout a user.

In the front end, I have a webpage that contains a power button icon, which on clicking should trigger a logout request.

I am using angular js for front end

index.html

<div class="col-xs-2">
     <span style="opacity: 0.5;font-family: FontAwesome;font-size: 14px;color:#838F98;text-align:center;cursor:pointer" ng-click="logout()">
               <i class="fa fa-power-off" aria-hidden="true"></i>
     </span>
</div>

Here I use ngclick to call the logout() function that is defined in my index.js

index.js

$scope.logout = function() {
       var url = '/logout';
       var toSend = {
          csrfmiddlewaretoken: '{{ csrf_token }}'
     }
   $http({
      method: 'POST',
      url: url,
      data: toSend,
   }).then(function(response) {
     response.data;
   })
  };

This function calls the /logout url for which I have defined an auth views in urls.py

urls.py

from django.contrib.auth.views import login, logout

url(r'^logout$', logout, {'template_name': 'login.html'}),

But when I click the power icon on the webpage, I get a 403 Forbidden error.It says CSRF verification failed. Request aborted.But I am passing the csrf token in the javascript POST call.

What am I doing wrong?

Souvik Ray
  • 2,899
  • 5
  • 38
  • 70

4 Answers4

1

Make sure to add the csrf token to the http request header in your config module as follow.

function config($httpProvider) {
    // state provider code

    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}

Also check that your django settings do not have:

CSRF_COOKIE_HTTPONLY=True

CSRF_COOKIE_HTTPONLY default is False but when True, client-side JavaScript will not to be able to access the CSRF cookie. Read more about this here

Marcell Erasmus
  • 866
  • 5
  • 15
0

When I get those errors is because the csrf token is not in the html form, this is a Django template tag , add it to your html template and then get the actual token by JavaScript to use it with angular The token will be hidden so inspect the html with your browser to see it to confirm that it works, the way you have it setup won’t work because you are passing a string of a template tag, Django is supposed to execute that tag in the html before you can captures it with JavaScript from your html tag and then you can post it to your view

<div class="col-xs-2">
{{ csrf_token }}
     <span style="opacity: 0.5;font-family: FontAwesome;font-size: 14px;color:#838F98;text-align:center;cursor:pointer" ng-click="logout()">
               <i class="fa fa-power-off" aria-hidden="true"></i>
     </span>
</div>
matiasm77
  • 87
  • 1
  • 3
0

Instead of passing CSRF Token at each AJAX call (which seems to be a headache and adds to the data array passed) you could make a function in jquery to save the CSRF token as a cookie.

Refer the docs.

Create a file "csrf_ajax.js" (or something of your choice) paste this in it.

function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        // 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;
}

var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

Load the script using static files or relative reference

Now you can make an AJAX call over POST request without worrying about the CSRF token.

Hope this helps you. Cheers

Kudos :)

Vivek
  • 322
  • 3
  • 14
0

You can try this :

Step1: Add django-cors-headers

setting.py
-----------
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'X-CSRFToken'
)

Add decorator in view

view.py
-------
from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def post(request):
    ## your logic

AngularJS Client side (add token to the request header)

$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;

You can follow this link

Kumar Akhil
  • 176
  • 7