Django Rest Framework custom authentication

How to implement a custom authentication scheme in DRF?

To implement a custom authentication scheme, we need to subclass the DRF’s BaseAuthentication class and override the .authenticate(self, request) method.

The method should return a two-tuple of (user, auth) if authentication succeeds, or None otherwise. In some circumstances, we may raise an AuthenticationFailed exception from the .authenticate() method.

Example (from DRF docs):

Lets say we want to authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'.

Step-1: Create the Custom authentication class

To do that, we will create an authentication.py file in my_app.

# my_app/authentication.py
from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions

class ExampleAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        username = request.META.get('X_USERNAME') # get the username request header
        if not username: # no username passed in request headers
            return None # authentication did not succeed

        try:
            user = User.objects.get(username=username) # get the user
        except User.DoesNotExist:
            raise exceptions.AuthenticationFailed('No such user') # raise exception if user does not exist 

        return (user, None) # authentication successful

Step-2: Specify the custom authentication class

After creating the custom authentication class, we need to define this authentication class in our DRF settings. Doing this, all the requests will be authenticated based on this authentication scheme.

'DEFAULT_AUTHENTICATION_CLASSES': (       
    'my_app.authentication.ExampleAuthentication', # custom authentication class
    ...
),

Note: If you want to use this custom authentication class on per-view basis or per-viewset basis and not on global level, you can define this authentication class explicitly in your views.

class MyView(APIView):

    authentication_classes = (ExampleAuthentication,) # specify this authentication class in your view

    ...

Leave a Comment