2
votes

I am currently running into the following issues with my Django Application and the django-rest-framework.

I have written a CustomAuthToken View according to: Django rest framework: Obtain auth token using email instead username

account/views.py

class UserView(APIView):

        def get(self, request):
        users = Customer.objects.all()
        serializer = CustomerSerializer(users, many=True)
        return Response(serializer.data)


class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (
        FormParser,
        MultiPartParser,
        JSONParser,
    )

    renderer_classes = (JSONRenderer,)

    def post(self, request):
        # Authenticate User
        c_auth = CustomAuthentication()
        customer = c_auth.authenticate(request)
        token, created = Token.objects.get_or_create(user=customer)

        content = {
            'token': unicode(token.key),
        }

        return Response(content)

My main urls.py:

    from rest_framework.urlpatterns import format_suffix_patterns

from account import views as user_view

urlpatterns = [
    url(r'users/$', user_view.UserView.as_view()),
    url(r'^api-token-auth/', user_view.ObtainAuthToken.as_view()),
    url(r'^auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
]

urlpatterns = format_suffix_patterns(urlpatterns)

My custom authentication.py:

    from django.contrib.auth.hashers import check_password

from rest_framework import authentication
from rest_framework import exceptions

from usercp.models import Customer


class CustomAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        email = request.POST.get('email')
        password = request.POST.get('password')
        if not email:
            return None
        if not password:
            return None

        try:
            user = Customer.objects.get(email=email)
            if check_password(password, user.password):
                if not user.is_active:
                    msg = _('User account is disabled.')
                customer = user
            else:
                msg = _('Unable to log in with provided credentials.')
                customer = None

        except Customer.DoesNotExist:
            msg = 'No such user'
            raise exceptions.AuthenticationFailed(msg)

        return customer

And taken from my settings.py:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

When I send my curl request:

curl -H "Accept: application/json; indent=4" -H "Authorization: Token bd97803941a1ede303e4fda9713f7120a1af656c" http://127.0.0.1:8000/users

I am getting back an "access denied".

The login works fine, I am receiving said token back.

However, I cannot access my Userview. I am not quite sure what the problem is. Would I need to change in the settings the TokenAuthentication? I don't think so. Since the user is set correctly in the database, even though I use a custom user object inherited from AbstractUser. From the documentation (http://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme) I think I do everything correctly as they use the same request Header, the spacing is correct and I don't think there is any encoding issue.

1
did you debug your authenticate method ? check if is working as expected.levi
How would you go about debugging it ? If I sent correct login credentials to it, I receive back a Token. if I send wrong credentials, I am not getting back a token.Richard
use this` import pdb` and then put this within your method pdb.set_trace(), now you can debug it using server console.levi

1 Answers

4
votes

After working out, that the Token was not forwarded in my WSGI configuration I re-read the documentation a bit more carefully.

http://www.django-rest-framework.org/api-guide/authentication/#apache-mod_wsgi-specific-configuration

Clearly states that WSGIPassAuthorization On needs to be configured for WSGI.