JWT or JSON Web Token is a security layer for your APIs. It will work as a gate pass for your API. We will implement JWT into our API server.

First open Terminal and run this command.

sudo pip3 install pyjwt

Go to quickstart folder > create a new folder named utils.

Create 3 files in the utils folder

__init__.py

token_generator.py

token_validator.py

Paste the code below into token_generator.py file

import jwt
from datetime import datetime, timedelta
from alert import settings

def generateAuthToken(email):
    iat = datetime.utcnow()
    exp = iat + timedelta(days=30)
    nbf = iat
    payload = {
        'exp': exp,
        'iat': iat,
        'nbf': nbf
        # 'aud': str(username)
    }
    if email:
        payload['sub'] = email

    tempData = jwt.encode(
        payload,
        str(settings.SECRET_KEY),
        algorithm='HS256'
    ).decode('utf-8')

    return tempData

Paste the code below into token_validator.py file


import jwt
from alert import settings

def tokenValidator(auth_header_value):
    if not auth_header_value:
        # return False
        return False

    parts = auth_header_value.split()

    if parts[0].lower() != 'bearer':
        # return False
        return False
    elif len(parts) == 1:
        # return False
        return False
    elif len(parts) > 2:
        return False
    else:
        try:
            
            payload = jwt.decode(parts[1], str(settings.SECRET_KEY), algorithms='HS256')
            # return payload['sub']
            which_user = payload['sub']

            return which_user

        except jwt.ExpiredSignatureError:
            # return 'Signature expired. Please log in again.'
            return False

        except jwt.InvalidTokenError:
            # return 'Invalid token. Please log in again.'
            return False

Update views.py file. Paste the code below and replace with existing code.


from rest_framework.views import APIView
from rest_framework.response import Response


from alert.alertapp.utils.token_generator import generateAuthToken
from alert.alertapp.utils.token_validator import tokenValidator


class WelcomeViewSet(APIView):
    def get(self, request, format=None):
        # Show a welcome greetings
        retJson = {
            "status": "ok",
            "msg": "Welcome Turzo! Your Django & MongoDB based API server is working successfully!"
        }

        return Response(retJson)




class LoginView(APIView):

    def post(self, request):
        data = request.data
        username = data.get('username', '')
        password = data.get('password', '')

        if username == 'turzo':
            # -- Generate an access token
            auth_token = generateAuthToken(username)
            retJson = {
                'status': 200,
                'msg': {
                    "access_token": auth_token
                }
            }
            return Response(retJson)
        else:
            retJson = {
                'status': 301,
                'msg': "Username or password is invalid"
            }
            return Response(retJson)

# -- Read the token
class ReadToken(APIView):
    def post(self, request):
        auth_header_value = request.META.get('HTTP_AUTHORIZATION', None)

        result = tokenValidator(auth_header_value)

        if not result:
            retJson = {
                'status': 200,
                 'msg': "Invalid access token"
            }
            return Response(retJson)
        else:
            retJson = {
                'status': 301,
                'msg': str(result)
            }
            return Response(retJson)







Add 2 new url path in urls.py file

path('api/login', views.LoginView.as_view()),
path('api/read', views.ReadToken.as_view()),

The urls.py file should look like this:

from django.urls import include, path
from rest_framework import routers
from alert.alertapp import views

#router = routers.DefaultRouter()
#router.register(r'users', views.WelcomeViewSet)


# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [

    path('api/welcome', views.WelcomeViewSet.as_view()),
    path('api/login', views.LoginView.as_view()),
    path('api/read', views.ReadToken.as_view()),

]

So, what we did?

By token_generator.py file, we are just creating a JWT token. We will call the token generating api by simply add a POST request into postman.

Request :

localhost:8000/api/login

Body ( RAW, JSON):

{
“username”: “turzo”,
“password”: “12243344”
}

If we hit the API, Response will be:

{
“status”: 200,
“msg”: {
“access_token”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MjY4NTc5NTcsImlhdCI6MTYyNDI2NTk1NywibmJmIjoxNjI0MjY1OTU3LCJzdWIiOiJ0dXJ6byJ9.xciC15DszNV43pXB793ggKZbKbgkZIszKP64wflTwZQ”
}
}

By token_validator.py file, we will read or validate the JWT token accordingly.

Request:

localhost:8000/api/read

Put the access token as Bearer Authorization Token which you got from the previous call:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MjY4NTc5NTcsImlhdCI6MTYyNDI2NTk1NywibmJmIjoxNjI0MjY1OTU3LCJzdWIiOiJ0dXJ6byJ9.xciC15DszNV43pXB793ggKZbKbgkZIszKP64wflTwZQ

When you hit the api, you will get the response below:

{
“status”: 301,
“msg”: “turzo”
}

If you entered the wrong access token, the response will be:

{
“status”: 200,
“msg”: “Invalid access token”

JSON Web Token or JWT successfully implemented with our server!

Leave a Reply

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