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
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 PUT, PATCH, POST 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
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.
ReplyBaltej 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.
ReplyMarie 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