How to Use API Authentication with Django Knox?

Published On: 05/01/2023 | Category: Django


Hi Dev,

In this tutorial we will go over the demonstration of how to use api authentication with django knox. I explained simply about django rest knox authentication example. you can see django api authentication with django knox example. I explained simply step by step how to integrate rest knox authentication in django. follow bellow step for how to create authentication with django knox api.

A framework called Django-Knox makes it simpler to authenticate API endpoints created using the Django Rest Framework. But like JSON Web Token (JWT) auth, Knox also uses tokens for authentication. For simple implementation, Django-Knox includes thorough documentation.

Here i will give you we will help you to give example of how to use api authentication with django knox. So let's see the bellow example:

Step 1: Create a Project

In this step, we’ll create a new django project using the django-admin. Head back to your command-line interface and run the following command:

django-admin startproject myproject
Step 2: Create an App
cd myproject
django-admin startapp base

Step 3: Install required library

Install Django and its prerequisites:

pip install django-rest-framework

Step 3: Update settings.py

Next, you need to add it in the settings.py file as follows:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'base', #new
    'accounts', #new
    'rest_framework', #new
    'knox', #new

]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication', ),
}

Step 4: Create a Model

Now go for the models we will We'll call our single model Lead and it will have just two fields: name, email, message and owner. And finally set __str__ to display the name of the lead in admin interface.

base/models.py
from django.contrib.auth.models import User
from django.db.models.deletion import CASCADE
from datetime import timezone

class Lead(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100, unique=True)
    message = models.CharField(max_length=500)
    owner = models.ForeignKey(User, related_name="leads", null=True, on_delete=CASCADE)

    def __str__(self):
        return self.name

Ok, all set. We can engender a migrations file for this change, then integrate it to our database via migrate.

python manage.py makemigrations
python manage.py migrate

Step 5: Creating the Serializers

In this step, we need to create Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data. Let’s start creating a serializer.

base/serializers.py
from rest_framework import serializers
from leadsapi.models import Lead

class LeadSerializer(serializers.ModelSerializer):

    class Meta:
        model = Lead
        fields = '__all__'

Step 6: Creating a api.py File

In this step we need to create a custom api.py file in base directory folder.

base/api.py
from rest_framework import serializers, viewsets, permissions

from leadsapi.models import Lead
from .serializers import LeadSerializer

class LeadViewset(viewsets.ModelViewSet):
    serializer_class = LeadSerializer
    permission_classes = [
        permissions.IsAuthenticated
    ]

    def get_queryset(self):
        return self.request.user.leads.all()
    
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
Step 7: Creating URLs

In this section, we need a urls.py file within the base app however Django doesn't create one for us with the startapp command. Create base/urls.py with your text editor and paste below code.

base/urls.py
from rest_framework import routers

from .api import LeadViewset

router = routers.DefaultRouter()
router.register('leads', LeadViewset, 'leads')

urlpatterns = router.urls
Step 8: Create a new App
django-admin startapp accounts
Step 9: Create a serializers.py file

In this step we require to create a serializers.py in our new accounts app.

accounts/serializers.py
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.db import models
from django.db.models import fields
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email')


class RegisterSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password')
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'])
        return user


class LoginSerializer(serializers.Serializer):
    username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, data):
        user = authenticate(**data)
        if user and user.is_active:
            return user
        raise serializers.ValidationError('Incorrect Credentials Passed.')

Step 10: Creating a api.py File

In this step we need to create a custom api.py file in base directory folder.

accounts/api.py
from django.contrib import auth
from rest_framework import generics, permissions, serializers
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import UserSerializer, RegisterSerializer, LoginSerializer

class SignUpAPI(generics.GenericAPIView):
    serializer_class = RegisterSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        token = AuthToken.objects.create(user)
        return Response({
            "users": UserSerializer(user, context=self.get_serializer_context()).data,
            "token": token[1]
        })


class SignInAPI(generics.GenericAPIView):
    serializer_class = LoginSerializer

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data
        return Response({
            "user": UserSerializer(user, context=self.get_serializer_context()).data,
            "token": AuthToken.objects.create(user)[1]
        })


class MainUser(generics.RetrieveAPIView):
  permission_classes = [
      permissions.IsAuthenticated
  ]
  serializer_class = UserSerializer

  def get_object(self):
    return self.request.user
accounts/urls.py
from django.urls import path, include
from .api import SignUpAPI, SignInAPI, MainUser
from knox import views as knox_views

urlpatterns = [
    path('api/auth/', include('knox.urls')),
    path('api/auth/register', SignUpAPI.as_view()),
    path('api/auth/login', SignInAPI.as_view()),
    path('api/auth/user', MainUser.as_view()),
    path('api/auth/logout',knox_views.LogoutView.as_view(), name="knox-logout"),
]

Next, we require to add a URL path for our base, accounts app which can be done by importing include and setting a path for it.

myproject/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('base.urls')),
    path('', include('accounts.urls')),
]
Run the Server

In this step, we’ll run the local development server for playing with our app without deploying it to the web.

python manage.py runserver

PostMan API Testing

I'm assuming you are aware that we must first register and then login in order to communicate with the API.

1. Send GET requests to http://localhost:8080/api/user and http://localhost:8080/api/leads respectively. A validation error ought to be sent since the user is not currently logged in.

I'm assuming you are aware that we must first register and then login in order to communicate with the API.

2. Make a POST call to http://localhost:8080/api/auth/register now, choosing raw » JSON under the body. Give the user a JSON object including their username, email, and password.



3. The token sent from the registration should be copied and pasted into the value field of the Authorization under the Headers section with the word Token prefixed, as seen below.



I Hope It will help you....