Django: User Authentication using knox

bhuma08

bhuma08

Posted on November 19, 2020

Django: User Authentication using knox

To get started, make sure you have django installed by using the command pipenv install django in your terminal. (Make sure you are in a virtual environment: pipenv shell)

Create a project django-admin startproject <project-name>. For this example, I will be creating a project about tvshows! So, my command will be django-admin startproject tvshows.

Now, cd into your project and make sure manage.py is in your root directory.

The command python manage.py runserver allows your app to be up and running. http://127.0.0.1:8000/ on your browser, should show this:

Next, create a superuser:python manage.py createsuperuser
This asks for a username, password and email address. Now that you have created a superuser, on the browser, add /admin to your initial site like this: http://127.0.0.1:8000/admin and your browser should show:

Use the username and password used to create the superuser to login! you should then see:

Now, you are ready to create user auth using knox where a token is generated for a user to login and access data.
You need to install the following:
pipenv install djangorestframework
pipenv install django-rest-knox

In settings.py, add:



INSTALLED_APPS = [
    ...
    'rest_framework',
    'knox'
]


Enter fullscreen mode Exit fullscreen mode

Now, let's create an app for our project.
Use python manage.py startapp <name> in the terminal. For now, I've used python manage.py startapp backend.

Your files in your code editor should look something like this:

Starting with Registration API:

In the backend folder, create a new file and name it serializers.py and add:



from rest_framework import serializers
from django.contrib.auth.models import User
from django.contrib.auth import authenticate

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

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

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


Enter fullscreen mode Exit fullscreen mode

Then, create an api.py file in the backend folder and add:



from rest_framework import viewsets, permissions, generics
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import CreateUserSerializer, UserSerializer

class RegistrationAPI(generics.GenericAPIView):
    serializer_class = CreateUserSerializer

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


Enter fullscreen mode Exit fullscreen mode

Now, to add the endpoints, create a urls.py file in the backend folder and add:



from django.urls import path
from .api import RegistrationAPI
from knox import views as knox_views

urlpatterns = [
    path('register/', RegistrationAPI.as_view()),
]


Enter fullscreen mode Exit fullscreen mode

You also need to add endpoint in urls.py file in the project folder which is tvshows in this case:



from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('backend.urls')),
    path('api/auth/', include('knox.urls'))
]


Enter fullscreen mode Exit fullscreen mode

Registration API is now complete. Next is creating a Login API.

In the serializers.py in your backend folder, add:



class LoginUserSerializer(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("Invalid Details.")


Enter fullscreen mode Exit fullscreen mode

Next, in api.py add:



from .serializers import CreateUserSerializer, UserSerializer, LoginUserSerializer

class LoginAPI(generics.GenericAPIView):
    serializer_class = LoginUserSerializer

    def post(self, request, *args, **kwargs):
        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]
        })


Enter fullscreen mode Exit fullscreen mode

You need to add the endpoints in urls.py in the backend folder:



from .api import RegistrationAPI, LoginAPI

urlpatterns = [
    ...,
    path('login/', LoginAPI.as_view()),
]


Enter fullscreen mode Exit fullscreen mode

Finally, you need an API to shows the user data when the user successfully logs in. To do this, you need to create a class in api.py file in your backend folder:



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

    def get_object(self):
        return self.request.user


Enter fullscreen mode Exit fullscreen mode

This needs an endpoint too. Therefore, in your urls.py in your backend folder, add:



from django.urls import path
from .api import RegistrationAPI, LoginAPI, UserAPI
from knox import views as knox_views

urlpatterns = [
    path('register/', RegistrationAPI.as_view()),
    path('login/', LoginAPI.as_view()),
    path('user/', UserAPI.as_view()),
]


Enter fullscreen mode Exit fullscreen mode

Now, you're all set. Make sure you run those migrations, using python manage.py makemigrations followed by python manage.py migrate.

You can use Postman to check if your endpoint work and you're able to do GET and POST requests.

Let's start with registration. You need to add header and a body to create a new user. So using the url http://127.0.0.1:8000/api/register/, add key Content-Type and value application/json on the header like this:

And add the body to POST to the API, like this:

Your registration has been successful!

You can now log in using http://127.0.0.1:8000/api/login/ and POST method adding the same body used to register. This generates a token:

You cannot access the user details without passing the token that was generated when successfully logging in, as seen below:

You are unable to view the user detail.

Therefore, you need to pass the token like this:

You are now able to view the user detail:

You can also see if the user was successfully created on django admin:

bhuma08 was the superuser I created at the beginning and user1 was created using Postman.

For logout functionality, just add a path in your backend/urls.py:



urlpatterns = [
    ...
    path('logout/', knox_views.LogoutView.as_view(), name='knox_logout')
]


Enter fullscreen mode Exit fullscreen mode

That's the end! :)

💖 💪 🙅 🚩
bhuma08
bhuma08

Posted on November 19, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Django: User Authentication using knox