Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return 401 when Auth Token is missing in Django Rest Framework

I'm finding hard to figure out how to return 401 when the token has been deleted in database for whatever reason.

Let me explain.

My general settings use SessionAuthentication and TokenAuthentication schemes.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.DjangoFilterBackend',
    ),
    'DATETIME_FORMAT': '%a, %d %b %Y %H:%M:%S %z',
    'DATETIME_INPUT_FORMATS': ['iso-8601', '%Y-%m-%d %H:%M:%S', '%a, %d %b %Y %H:%M:%S %z'],
    'DATE_FORMAT': '%Y-%m-%d',
    'DATE_INPUT_FORMATS': ['%Y-%m-%d', '%m/%d/%YYYY'],
    'PAGE_SIZE': 20
}

I have a view for generating the Auth Token, like this:

class AcmeObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
    renderer_classes = (renderers.JSONRenderer,)
    serializer_class = AcmeAuthTokenSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.context = {'request': self.request}
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)
       return Response({'token': token.key,
                     'school': school,
                     'user': user.id})

obtain_auth_token = AcmeObtainAuthToken.as_view()

My problem is that when token stored in db is gone for whatever reason and clients send the token, I'm getting 403, when I require 401.

Looking at the docs this is really cryptic:

The kind of response that will be used depends on the authentication scheme. Although multiple authentication schemes may be in use, only one scheme may be used to determine the type of response. The first authentication class set on the view is used when determining the type of response.

It says it depends but how? No example is given...kinda confusing on how DRF does its magic under the hood here...

like image 915
AlejandroVK Avatar asked Jun 21 '17 07:06

AlejandroVK


People also ask

How do I use authentication credentials in Django?

from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an 'invalid ...

Where are Django JWT tokens stored?

If you actually need JWTs, you should store them in a secure Cookie and they should have a very short TTL. The refresh token that allows you to refresh the JWT should be stored in a secure + HTTP only cookie. You should never store anything with personal or authentication related information in local storage.


1 Answers

403 is the response you should get in that instance. Have a look at this link:

The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated.

In essence, the client made a correct request but the token is missing, therefore his access is forbidden (403).

If you really want to respond with a 401 error, you can try something like the following in your BloowatchObtainAuthToken view:

class BloowatchObtainAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        response = super(BloowatchObtainAuthToken, self).post(request, *args, **kwargs)
        try:
            token = Token.objects.get(user=request.user) # or what you are validating against
            other stuff here...
        except Token.DoesNotExist:
            return Response({'error': 'Token does not exist'}, status=401)
like image 71
John Moutafis Avatar answered Oct 16 '22 17:10

John Moutafis