JoakimB JoakimB - 4 years ago 127
AngularJS Question

AngularJS + Django Rest Framework + CORS ( CSRF Cookie not showing up in client )

I am developing a 1-page application in AngularJS using and Django Rest Framework + Django CORS Headers.

My problem is that the "csrftoken" cookie never shows up in my browser when I have contacted the backend.

For example: I am doing a login using a post. I get the "sessionid" cookie properly but the "csrftoken" never shows up and therefor I cannot do proper posts from my client since I will get denied due the lack of the csrf token.


  • I have analyzed the response headers from the API and the csrftoken is not ther.

  • I have looked directly in the rest API browser and it shows up fine there.

  • Just to point out, I can do my first POST to login since Django Rest Framework only forces CSRF for authenticated users. If I try to relogin it will fail since the "sessionid"-cookie it present.

  • I am not interessted in bypassing the CSRF protection as some posts on stackoverflow suggests.



Some code snippets from front/backend. These are unfinnished snippets, so dont get hung up on poorly written code.

Backend API LoginView



class LoginView(APIView):

renderer_classes = (JSONPRenderer, JSONRenderer)

def post(self, request, format=None):
serializer = LoginSerializer(data=request.DATA)

if serializer.is_valid():
userAuth = authenticate(username=serializer.data['username'], password=serializer.data['password'])

if userAuth:

if userAuth.is_active:
login(request, userAuth)

loggedInUser = AuthUserProfile.objects.get(pk=1)
serializer = UserProfileSerializer(loggedInUser)

user = [serializer.data, {'isLogged': True}]



else:
user = {'isLogged': False}

return Response(user, status=status.HTTP_200_OK)

return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


Client side AngularJS Login Controller



.controller('LoginCtrl', ['$scope', '$http', 'uService', '$rootScope', function(scope, $http, User, rootScope) {

scope.login = function() {

var config = {
method: 'POST',
withCredentials: true,
url: rootScope.apiURL+'/user/login/',
data : scope.loginForm
};

$http(config)
.success(function(data, status, headers, config) {

if (status == 200) {
console.log(data[0]); //Test code
// succefull login
User.isLogged = true;
User.username = data.username;

}
else {
console.log(data); //Test code
User.isLogged = false;
User.username = '';
}

})
.error(function(data, status, headers, config) {
console.log('Testing console error');
User.isLogged = false;
User.username = '';
});
};


}]);

Anyone with any good tips/ideas/examples?

Answer Source

So I found my own solution to this, seems to work great.

This is the new snippets of my code:

Backend API LoginView ( added a decorator forcing the csrf token to be added to the body )

class LoginView(APIView):

renderer_classes = (JSONPRenderer, JSONRenderer)

@method_decorator(ensure_csrf_cookie)
def post(self, request, format=None):
    c = {}
    c.update(csrf(request))
    serializer = LoginSerializer(data=request.DATA)

    if serializer.is_valid():
        userAuth = authenticate(username=serializer.data['username'], password=serializer.data['password'])

        if userAuth:

            if userAuth.is_active:
                login(request, userAuth)

                loggedInUser = AuthUserProfile.objects.get(pk=1)
                serializer = UserProfileSerializer(loggedInUser)

                user = [serializer.data, {'isLogged': True}]



        else:
            user = {'isLogged': False}

        return Response(user, status=status.HTTP_200_OK)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

AngularJS Client side ( add token to the request header )

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

Server side settings file ( Specificly for django-cors-headers )

First 5 are added by default, but you need to add "X-CSRFToken" to allow such a header from the client to the API using CORS, else the post will be denied.

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

)

Thats it!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download