9

I have the following code:

The problem is when I try to access user-login/ I get an error: "CSRF Failed: CSRF cookie not set."

What can I do?

I am using the django rest framework.

urls.py:

url(r'^user-login/$', 
    csrf_exempt(LoginView.as_view()),
    name='user-login'),

views.py:

class LoginView(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
    startups = Startup.objects.all()
    serializer = StartupSerializer(startups, many=True)
    return Response(serializer.data)

def post(self, request, format=None):
    profile = request.POST

    if ('user_name' not in profile or 'email_address' not in profile or 'oauth_secret' not in profile):
        return Response(
            {'error': 'No data'},
            status=status.HTTP_400_BAD_REQUEST)

    username = 'l' + profile['user_name']
    email_address = profile['email_address']
    oauth_secret = profile['oauth_secret']
    password = oauth_secret
pixelistik
  • 7,541
  • 3
  • 32
  • 42
user2237822
  • 605
  • 2
  • 10
  • 13

4 Answers4

14

I assume you use the django rest framework SessionBackend. This backend does a implicit CSRF check

You can avoid this by:

from rest_framework.authentication import SessionAuthentication

class UnsafeSessionAuthentication(SessionAuthentication):

    def authenticate(self, request):
        http_request = request._request
        user = getattr(http_request, 'user', None)

        if not user or not user.is_active:
           return None

        return (user, None)

And set this as authentication_classes in your View

class UnsafeLogin(APIView):
    permission_classes = (AllowAny,) #maybe not needed in your case
    authentication_classes = (UnsafeSessionAuthentication,)

    def post(self, request, *args, **kwargs):

        username = request.DATA.get("u");
        password = request.DATA.get("p");

        user = authenticate(username=username, password=password)
        if user is not None:
           login(request, user)

        return redirect("/")
maersu
  • 3,242
  • 22
  • 27
13

Actually, better way to disable csrf check inside SessionAuthentication is:

from rest_framework.authentication import SessionAuthentication as OriginalSessionAuthentication

class SessionAuthentication(OriginalSessionAuthentication):
    def enforce_csrf(self, request):
        return
Alexander Artemenko
  • 21,378
  • 8
  • 39
  • 36
2

The easiest way to solve this problem:

For that there are two ways of authentication in drf see drf auth

BasicAuthentication

SessionAuthentication (default)

SessionAuthentication has a forced csrf check, but BasicAuthentication doesn't. So my way is using BasicAuthentication in my view instead of SessionAuthentication.

from rest_framework.authentication import BasicAuthentication

class UserLogin(generics.CreateAPIView):
    permission_classes = (permissions.AllowAny,)
    serializer_class = UserSerializer
    authentication_classes = (BasicAuthentication,)

    def post(self, request, *args, **kwargs):
        return Response({})
Anderson
  • 21
  • 2
0

Probably better to just make the enforce_csrf check do nothing:

from rest_framework.authentication import SessionAuthentication

class UnsafeSessionAuthentication(SessionAuthentication):

    def enforce_csrf(self, *args, **kwargs):
        '''
        Bypass the CSRF checks altogether
        '''
        pass

Otherwise you'll possibly end up with issues in the future if the upstream authenticate() method changes. Also, it's MUCH simpler to just make the check not do anything :-)

chander
  • 1,997
  • 2
  • 16
  • 15