JWT(Json Web Token) In Django REST API


 

Whenever we send a request to the server, it should be Authorize and Authenticate, Now what is the main difference between them? 

 

Authorization

The authorization will check the following points for logged-in user 

  1. Verifies is access allowed through policies and rules

  2. Determine what the user can or cannot access 

  3. Usually this part check after the successful completion of Authentication

 

Authentication:

The first step is authentication itself, in which it will check whether is the user is valid or not via token ID. Token ID is the unique key/ identification to say I'm the valid customer/owner of an application.

we have many authentication types such as Basic Authentication, Session Authentication, Custome Authentication (We can create our Authentication), and JSON Web Tokens(JWT)

In this tutorial, we are going to see how to implement Authentication in DRF (Django REST Framework ) using JWT. We first see a normal method by login using the username, password, and then we create JWT token with mobile number login also. 


JWT(JSON Web Tokens):

JSON Web Token (JWT) is a compact claims representation format intended for space-constrained environments such as HTTP Authorization headers and URI query parameters. JWTs encode claims to be transmitted as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the.

Plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. JWTs are always represented using the JWS Compact Serialization or the JWE Compact Serialization.

 

Working Flow Of JWT.

 

 

In the example, the user signs into the server using the authentication server’s login system (e.g. username and password, Facebook login, Google login, etc). The authentication server creates the JWT and sends it to the user. When the user makes API calls to the application, the user passes the JWT along with the API call.


In this setup, the application server would be configured to verify that incoming JWT is created by the authentication server (the verification process will be explained in more detail later). So, when the user makes API calls with the attached JWT, the application can use the JWT to verify that the API call is coming from an authenticated user.

Now, the JWT itself, and how it’s constructed and verified, will be examined in more depth with the below topics

 

  • How JWT works
  • Installation and Service
  • Example
  • uses
    • a. Obtain token
    • b. Refresh token
  • Point of the refresh token

How JWT Works?

 

The JWT is just an authorization token that should be included in all requests:

curl http://127.0.0.1:8000/ -H 'Authorization: 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6ImFqaXQiLCJleHAiOjE1NzEyOTU0NDAsIm9yaWdfaWF0IjoxNTYyNjU1NDQwfQ.
SlGhifEmjOJoExRUe4Sfk0GzyykT9tOB3b9VTwKcQxI'

 

The JWT is acquired by exchanging a username + password for an access token and a refresh token.

The access token is usually short-lived (expires in 5 min or so, can be customized though).

The refresh token lives a little bit longer (expires in 24 hours, also customizable). It is comparable to an authentication session. After it expires, you need a full login with username + password again.

 

Why is the Token Structure?

It’s a security feature and also it’s because the JWT holds a little bit more information. If you look closely the example I gave above, you will see the token is composed of three parts separated by a dot(‘.’)

xxxxx.yyyyy.zzzzz

 

This is three distinctive parts that compose a JWT:

header.payload.signature

 

see like below

Header:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9,
Payload:eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6ImFqaXQiLCJleHAiOjE1NzEyOTU0NDAsIm9yaWdfaWF0IjoxNTYyNjU1NDQwfQ,
Signture:SlGhifEmjOJoExRUe4Sfk0GzyykT9tOB3b9VTwKcQxI

 

This information is encoded using Base64. If we decode, we will see something like this:

Header :(ALGORITHM & TOKEN TYPE)
The header indicates what type of web token we are using and which algorithm we opt as below

{   
    "typ": "JWT",
    "alg": "HS256" 
}

 

Payload:(DATA)
Payload indicates the data of the user, you can see below which contains the user_id and some of the user details.

{
  "user_id": 5,
  "username": "ajit",
  "exp": 1571295440,
  "orig_iat": 1562655440
}

 

Signature:

The signature is issued by the JWT backend, using the header base64 + payload base64 + SECRET_KEY. Upon each request, this signature is verified.
If any information in the header or the payload was changed by the client it will invalidate the signature. The only way of checking and validating the signature is by using your application’s SECRET_KEY. Among other things, that’s why you should always keep your "SECRET_KEY"  secret!

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret 
)

 

Installation and Setup:

For this tutorial, we are going to use the djangorestframework_simplejwt library, recommended by the DRF developers.

pip install djangorestframework-jwt

 

Paste line in installed App;

'rest_framework',
'rest_framework.authtoken',

 

settings.py

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=100),
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=100),
    'JWT_ALLOW_REFRESH': True,
    'JWT_AUTH_HEADER_PREFIX': 'Token',
    'JWT_DECODE_HANDLER':
                    'rest_framework_jwt.utils.jwt_decode_handler',
    'JWT_SECRET_KEY': settings.SECRET_KEY,
}
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'] }

 

Refresh Token:
Whatever we got the token that called access token is usually short-lived (expires in 5 min or so, can be customized though).

The refresh token lives a little bit longer (expires in 24 hours, also customizable). It is comparable to an authentication session. After it expires, you need a full login with username + password again.

 

Point Of Refresh Token:


At first glance, the refresh token may look pointless, but in fact, it is necessary to make sure the user still has the correct permissions. If your access token has a long expire time, it may take longer to update the information associated with the token. That’s because the authentication check is done by cryptographic means, instead of querying the database and verifying the data. So some information is sort of cached.

There is also a security aspect, in the sense that the refresh token only travels in the POST data. And the access token is sent via HTTP header, which may be logged along the way. So this also gives a short window, should your access token be compromised.

In Django, We gave the access token time in settings.py

'JWT_EXPIRATION_DELTA': datetime.timedelta(days=100),
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=100),
'JWT_ALLOW_REFRESH': True,

 

With this, we can customize the time delta fro access token and fresh token.

If you fetch any problem while installing follow below command

pip install djangorestframework
python3 -m pip install --upgrade pip
pip install djangorestframework-jwt

 

Example

1) Using the normal method, sign in using username and password 

Urls.py 

 

from django.contrib import admin
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token

from jwt_username_app.views import userview

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^auth-jwt/', obtain_jwt_token),
    url(r'api/v1/emp', userview.as_view()),
    url(r'^auth-jwt-refresh/', refresh_jwt_token),
    url(r'^auth-jwt-verify/', verify_jwt_token),
]

 

Views.py

 

 

from django.shortcuts import render
from rest_framework.authentication import TokenAuthentication
from rest_framework.generics import ListCreateAPIView

from jwt_username_app.models import emp
from jwt_username_app.serializers import empSerializer


class userview(ListCreateAPIView):
    queryset = emp.objects.all()
    serializer_class = empSerializer
    authentication_classes = [TokenAuthentication]

 

Results :



So first it asked for user credentials, It will generate Token if you provide the correct credentials as below image 

 

Now let's see How was the behavior when we don't have the token and what if we have a token 

 

When We don't pas the Token to Server

The Lates picture talks about when we don't pass the token to the server, its saying Authentication not provided, Let's see what if I provide the correct token 

Succesfull result

That's All about the JWT via Username and password,

2) Let's see the Authentication via Mobile phone number. 

 

 

Models.py

from django.db import models

class userdetails(models.Model):
    phone=models.BigIntegerField(max_length=10)
    username=models.CharField(max_length=30)
    gender=models.CharField(max_length=6)
    state=models.CharField(max_length=20)
    obeject=models.Manager()

    def __str__(self):
        return self.username

 

Serializers.py

 

from django.contrib.auth import get_user_model
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings



from .models import userdetails


class jwtserializer(serializers.ModelSerializer):
    UserModel = get_user_model()
    token = serializers.SerializerMethodField()

    def get_token(self, obj):
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(obj)
        token = jwt_encode_handler(payload)
        return token

    class Meta:
        model = userdetails
        fields = '__all__'

 

Views.py

from django.contrib.auth import get_user_model
from django.shortcuts import render
from rest_framework import generics
from rest_framework import permissions

from jwtapp.models import userdetails
from jwtapp.serializer import jwtserializer


class UserView(generics.ListCreateAPIView):
    model=get_user_model()
    permission_classes = [
        permissions.AllowAny
    ]
    queryset = userdetails.obeject.all()
    serializer_class = jwtserializer


'''To Display All Data present in userdetails'''

class Userdetails(generics.RetrieveUpdateDestroyAPIView):
    queryset = userdetails.obeject.all()
    serializer_class = jwtserializer

'''To Display The data according the PK value from userdetails data'''

class Detailstodo(generics.RetrieveUpdateDestroyAPIView):
    model = get_user_model()
    permission_classes = [
        permissions.AllowAny
    ]
    queryset = userdetails.obeject.all()
    serializer_class = jwtserializer

 

URLs:
This is from project URLs, make one more URLs file at the application level so we can include the main URL from project/URLs to project/application/URLs as below

project/URLs

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('jwtapp.urls')),
]

project/application/URLs

from django.urls import path
from jwtapp.views import UserView,Userdetails,Detailstodo

urlpatterns = [
    path('',UserView.as_view()),
    path('<int:pk>',Userdetails.as_view())
]

Result:

 

 

 

For more Code see the code section with the same title or you can visit my GitHub link 

That's All About JWT with 2 real-time example 

Happy Pythoning !!!!


© 2020 Blog, All rights reserved.   This work is licensed under  Creative Commons License
Top