Blog (or) Scribble Pad

Token based, authenticated REST API's using Django Rest Framework (DRF)

Add rest_framework and rest_framework.authtoken to installed apps in Django project settings file

First install DRF

$ pip install djangorestframework

then add the DRF to installed apps,

INSTALLED_APPS = (
#    'django_admin_bootstrapped',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
    '.....',
    )

and run migrations for the DRF,

$ python manage.py makemigrations
$ python manage.py migrate

Token generation code for each new user to be created (in relevent models file)

# models.py

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)

for already existing users, the token can be generated by running the below snippet in django shell

# python manage.py shell

from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

for user in User.objects.all():
    Token.objects.get_or_create(user=user)

Adding API endpoint for getting tokens

# urls.py

from rest_framework.authtoken import views
from myapp.views import MyView
urlpatterns += [
    url(r'^get/my/view/$', MyView.as_view()),
    url(r'^token/', views.obtain_auth_token),
]

Adding an API endpoint view under token authentication

For class based views

# views.py

from django.http import JsonResponse
from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class MyView(APIView):
    """ subclass from APIView inorder to use the token based authentication provided by DRF"""
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        return JsonResponse({'Data':'My View'})

For function based views

#views.py

from django.http import JsonResponse
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

@api_view(['GET'])
@authentication_classes((TokenAuthentication,))
@permission_classes((IsAuthenticated,))
def my_view(request, format=None):
    return JsonResponse({'Data':'My View'})

testing

Once everything has been done, create a user and test if everything works fine.

$ curl -X POST -d 'username=username&password=password' localhost:8000/token/
{"token":"6874e18a8e754df76ab140744c9310142e6f8943"}
$ curl -H "Authorization: Token 6874e18a8e754df76ab140744c9310142e6f8943" http://localhost:8000/get/my/view/
{'Data':'My View'}
$ curl http://localhost:8000/get/my/view/
{"detail": "Authentication credentials were not provided."}