blog image

In this tutorial we will learn about the authentication in Django Rest Framework.

Authentication:

Authentication is a process of confirming the identity of users and if the user is authorized to access a requested resource.

Define Authentication

The default Authentication may be set globally in setting.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

You can also set the authentication policy on a per-view, or per-viewset basis

from rest_framework.viewsets import ModelViewSet
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = (IsAuthenticated,)
    http_method_names = ['post', ]

Types of Authentication schemes:-

  • BasicAuthentication
  • TokenAuthentication
  • SessionAuthentication
  • RemoteUserAuthentication
  • Custom authentication

BasicAuthentication

Basic authentication uses username and password to authenticate. Basic authentication is generally only appropriate for testing.

if successfully authenticated ,it provides the following credentials.

.request.user will be a django user instance

.request.auth will be None

views.py

from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import BasicAuthentication
from api.serializer import PostSerializer
from myapp.models import Post


class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = (IsAuthenticated,)
    authentication_classes = [BasicAuthentication]
    http_method_names = ['get', ]

Now when you try to access API, it will ask for your username and password

TokenAuthentication

Token authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.

views.py

from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from api.serializer import PostSerializer
from myapp.models import Post


class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = (IsAuthenticated,)
    authentication_classes = [TokenAuthentication]
    http_method_names = ['get', ]

 

SessionAuthentication

Session authentication uses Django's default session backend for authentication. Session authentication allows you to authenticate users very similar to the way Django authenticates users without Django REST Framework. Session authentication is appropriate for AJAX clients that are running in the same session context as your website.

if successfully authenticated ,it provides the following credentials.

.request.user will be a django user instance

.request.auth will be None

unauthenticated responses that are denied permission will result in on Http 403 forbidden response.

api/views.py

from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated, AllowAny  # NOQA
from rest_framework.authentication import SessionAuthentication
from api.serializer import PostSerializer
from myapp.models import Post


class PostViewSet(ModelViewSet):
    queryset = Post.objects.none()
    serializer_class = PostSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = (IsAuthenticated,)
    http_method_names = ['post', ]

If you are using Session authentication you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as PUTPATCHPOST or DELETE requests. 

 

 

JWT Authentication

def generate_access_token(user):
    access_token_payload = {
        'user_id': user.id,
        "is_superuser": user.is_superuser,
        "password": user.password,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(days=10, minutes=30),
        'iat': datetime.datetime.utcnow(),
    }
    access_token = jwt.encode(access_token_payload, settings.KEY, algorithm='HS256')
    return access_token


def generate_refresh_token(user):
    refresh_token_payload = {
        'user_id': user.id,
        "password": user.password[-30:],
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30),
        'iat': datetime.datetime.utcnow()
    }
    refresh_token = jwt.encode(
        refresh_token_payload, settings.KEY, algorithm='HS256')
    return refresh_token

CustomAuthentication

To implement the custom authentication scheme,subclass BaseAuthentication and override the authenticate(self,request)

The method should return a two_tuple of (user,auth) if authentication success or None otherwise.

from .models import User, UserRole
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from rest_framework import permissions
import datetime
import jwt
from django.conf import settings


class SafeJWTAuthentication(BaseAuthentication):

    def authenticate(self, request):
        authorization_header = request.headers.get('Authorization')
        if not authorization_header:
            return None
        try:
            access_token = authorization_header.split(' ')[1]
            payload = jwt.decode(access_token, settings.KEY, algorithms=['HS256'])

        except jwt.ExpiredSignatureError:
            raise exceptions.AuthenticationFailed('access_token expired')
        except IndexError:
            raise exceptions.AuthenticationFailed('Token prefix missing')
        except Exception:
            raise exceptions.AuthenticationFailed("Invalid Access Token")

        u_id = payload['user_id']
        user = User.objects.filter(id=u_id).first()

        if user is None:
            raise exceptions.AuthenticationFailed('User not found')

        if not user.is_active:
            raise exceptions.AuthenticationFailed('user is inactive')

        if user.password[-30:] != payload["password"][-30:]:
            raise exceptions.AuthenticationFailed('Password changed.Please logged in again.')
        return user, None

example of simple custom authentication

#custom_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from accounts.models import CustomUser
class CustomAuthentication(BaseAuthentication):
    def authenticate(self, request):
        username=request.GET.get("username")
        if username is None:
            return None
        try:
            user=CustomUser.objects.get(username=username)
        except CustomUser.DoesNotExist:
            raise AuthenticationFailed("No such User")
        return (user,None)

#views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.authentication import BasicAuthentication
from .custom_auth import CustomAuthentication

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    authentication_classes = [CustomAuthentication]
    permission_classes = (IsAuthenticated,)
    http_method_names = ['post' ]

then user can hit the url like:

http://127.0.0.1:8000/studentapi/?username=ram


About author

author image

Amrit Panta

Python developer, content writer



3 Comments

Amanda Martines 5 days ago

Exercitation photo booth stumptown tote bag Banksy, elit small batch freegan sed. Craft beer elit seitan exercitation, photo booth et 8-bit kale chips proident chillwave deep v laborum. Aliquip veniam delectus, Marfa eiusmod Pinterest in do umami readymade swag. Selfies iPhone Kickstarter, drinking vinegar jean.

Reply

Baltej Singh 5 days ago

Drinking vinegar stumptown yr pop-up artisan sunt. Deep v cliche lomo biodiesel Neutra selfies. Shorts fixie consequat flexitarian four loko tempor duis single-origin coffee. Banksy, elit small.

Reply

Marie Johnson 5 days ago

Kickstarter seitan retro. Drinking vinegar stumptown yr pop-up artisan sunt. Deep v cliche lomo biodiesel Neutra selfies. Shorts fixie consequat flexitarian four loko tempor duis single-origin coffee. Banksy, elit small.

Reply

Leave a Reply

Scroll to Top