How to enable TokenAuthentication scheme | Django Rest Framework

neotam Avatar

How to enable TokenAuthentication scheme | Django Rest Framework

Authentication and Authorisation is the key to protect resource on the web server. There are different types of authentication models such as Basic, Token and Session. Thanks to Django Rest Framework, it provides a work with one or many of these authentication schemes

Django rest framework supports multiple authentication backends

Simple steps involving in enabling TokenAuthentication in you application

  1. Add “rest_framework.authtoken” to INSTALLED_APPS
INSTALLED_APPS = [   
 ...     
'rest_framework.authtoken' 
]

Once ‘rest_framework.authtoken’ is added to INSTALLED_APPS, run migrate command

python manage.py migrate 

Set the authentication backend

AUTH_USER_MODEL = 'app.User'  #User Model which contains username/email and password

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',

)

Make sure the Mode “app.User” is replaced with appropriate mode that represents the user accounts on the site

For Django rest framework, default authentication classes can be provided in settings.py using following setting as follows

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [

        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ]
}

As we can see, multiple authentication classes DRF (Django Rest Framework) uses the most appropriate one based on the request

You can generate a token for any arbitrary user from command line using Django manage.py command “drf_create_token” as follows

python manage.py drf_create_token suraj@gmail.com
Generated token 35e9b1ad42d7579c2cd70cb43837ae4690f5908a for user suraj@gmail.com

To generate token for any user automatically when user is being created, register the receiver for the signal post_save for the user model

from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

Ideal place to have the above code is models.py, or it can also be placed anywhere which can be imported by Django on startup

Add the end point to allow clients to get access token by providing the valid username and password. Add the following path in urls.py

from rest_framework.authtoken import views

urlpatterns = [
...
path('api-token-auth/', views.obtain_auth_token)
...
]

It is not mandatory to use the path ‘api-token-auth’ you can provide access token on any endpoint for example: api-token instead of api-token-auth etc.

Or, add the following statement at the end of the module of urls.py

urlpatterns += [
    path('api-token-auth/', views.obtain_auth_token)
]

Django rest framework enforces the checking of CSRF token, only if it is SessionAuthentication. Thus, csrftoken to be sent as X-CSRFToken. It is not required for TokenAuthentication.

From Client Side

Client should send the “Authorization” header with token prefixed with “Token” string literal seperated by space as follows

Authorization: Token 2abcd468eaa84cb4105b3320124f567cc24f2cc5

Trouble Shooting

  1. Did you add ‘rest_framework.authtoken’ to INSTALLED_APPS list in settings.py ?
  2. If you are using django.contrib.auth.backends.ModelBackend, make sure AUTH_USER_MODEL is pointing to the right model
  3. Check if “TokenAuthentication” is specified in the “DEFAULT_AUTHENTICATION_CLASSES” (of REST_FRAMEWORK setting)
  4. If CSRF token is troubling you, disable it by removing or commenting ‘django.middleware.csrf.CsrfViewMiddleware’ from MIDDLEWARE list in the settings.py
  5. If you are getting following error
Forbidden (403)
 CSRF verification failed. Request aborted.
 Help
 Reason given for failure:
 CSRF token missing or incorrect.

Either disable django.middleware.csrf.CsrfViewMiddleware as mentioned in point 3 or use csrf_exempt decorator (django.views.decorators.csrf.csrf_exempt) or use the following custom class

from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response

class CustomAuthToken(ObtainAuthToken):

    permission_classes = []
    authentication_classes = []
    
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data,
                                           context={'request': 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
        })

Make sure, above customized view is included in urls.py as follows

urlpatterns += [
    path('api-token-auth/', CustomAuthToken.as_view())
]

5. Did you include “rest_framework.authentication.TokenAuthentication” in DEFAULT_AUTHENTICATION_CLASSES list of REST_FRAMEWORK setting in settings.py file ?

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 'CsrfExemptSessionAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ]
}

Leave a Reply

Your email address will not be published. Required fields are marked *