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
- 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
- Did you add ‘rest_framework.authtoken’ to INSTALLED_APPS list in settings.py ?
- If you are using django.contrib.auth.backends.ModelBackend, make sure AUTH_USER_MODEL is pointing to the right model
- Check if “TokenAuthentication” is specified in the “DEFAULT_AUTHENTICATION_CLASSES” (of REST_FRAMEWORK setting)
- If CSRF token is troubling you, disable it by removing or commenting ‘django.middleware.csrf.CsrfViewMiddleware’ from MIDDLEWARE list in the settings.py
- 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',
]
}