Authentication In Django Rest Framework

Authentication In Django Rest Framework

In previous articles we have developed an open API i.e any user (Authenticated and Un-authenticated) can access the API resource. If we want to want to know the information who is accessing the API then we have to authenticate the user. Authentication means the process or action of verifying the identity of a user. REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes. In Django REST framework do not restrict the user access to the API resource. If we want to restrict the user access to the API then we have use permissions and throttling classes. We can discuss about it in coming articles.

Authentication Flow in DRF

Whenever any request comes to Django Rest API view first it passed to method def dispatch(self, request, *args, **kwargs), it will take the list of all available authentication classes from the view attribute "authentication_classes" and it takes one class at a time from the "authentication_classes" and tries to authenticate the user with the authentication class if the class is able to authenticate the user then it will assign the property "user" to the "request" object. So, we can access the user like "request.user" to get the user in the view. If all of the authentication classes failed to authenticate the user then an "AnonymousUser" object is assigned to "request.user" . If one of authentication classes is able to authenticate the user then all other authentication classes will be skipped or will not processed further.

Default Authentication Classes provided by DRF

By default Django REST Framework provides two authentication classes. Below two classes are used to authenticate the user unless we override "authentication_classes" in the API view.

  1. rest_framework.authentication.BasicAuthentication

  2. rest_framework.authentication.SessionAuthentication

Gobally configuring the authentication scheme in settings.py

We can override the default authentication classes provided by DRF in settings.py with the below configuration. We can also use our custom authentication classes and configure like below.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        # 'myapp.authentication.CustomAuthentication',
    )
}

In above code we have configured authentication globally(i.e throughout the app). We can also set authentication scheme per view or per viewset basis.

How to override the global authentication classes in Views or Viewsets ?

We can override the default authentication classes in views, But View must be subclass of "APIView". I personally do not recommend using function based views because, it internally uses classbased views code and we have to write more code. so, I recommend avoid using the function based views. To override the authentication classes in views we have to set the attribute "authentication_classes". It takes the iterable datatype. Please checkout the example code below.

from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class AuthExampleAPIView(APIView):
    authentication_classes = (BasicAuthentication, )

    def get(self, request, format=None):
        content = {
            'user': str(request.user)
        }
        return Response(content)

Setting Up Token Authentication in Django REST Framework

In addition to "BasicAuthentication", "SessionAuthentication" DRF also provides another authentication scheme called TokenAuthenticaction. You may get question, why we need token authentication ? The general concept behind a token-based authentication system is simple. Allow users to enter their username and password in order to obtain a token which allows them to fetch a specific resource - without using their username and password. To use token based authentication in Dango REST Framework we need to do the following configurations.

settings.py

INSTALLED_APPS = (
    'rest_framework',
    'rest_framework.authtoken',
    'myapp',
)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

urls.py

from rest_framework.authtoken.views import ObtainAuthToken
from . import views
urlpatterns = [
    path('api/protected/', views.ProtectedAPIView.as_view(), name='protected'),
    path('api/token-auth/', ObtainAuthToken, name='auth_token'),
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class ProtectedAPIView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        data = {'message': 'I am proteted'}
        return Response(data)

How to get auth token ?

To get auth token we have to send a "POST" request to the api endpoint "/api/token-auth/" with user credentials. Let's see an exmaple request below. I prefer using postman to test the apis but, let's use python requests to test the above api endpoints.

import requests
params = {"username": "admin", "password": "secret"}
headers = {"content-type": "application/json"}
r = requests.post("https://localhost:8000/api/token-auth/", params, headers)
print(r.json())
# Output: {"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"}

How to use obtained auth token ?

Let's use the above obtained token to access protected resource. Let's see an example request below.

import requests
headers = {"Authorization": "Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b", "content-type": "application/json"}
r = requests.get("https://localhost:8000/api/protected/", headers=headers)
print(r.json())
# Output: {"message": "I am protected"}

To learn better is to practice what you have learnt. So, try all the above code and let me know if you get any doubts in the below comments.

References: https://www.django-rest-framework.org/api-guide/authentication/