From 8ab7d6ad73b07dbdb808a0b7ccd9a1e6d40c42aa Mon Sep 17 00:00:00 2001 From: Sumit Singh Date: Mon, 4 Dec 2023 12:58:36 +0530 Subject: [PATCH] Rewrite JSONWebTokenAuthenticationQS in core module --- HisabKitab/custom_settings.py | 2 +- HisabKitab/settings.py | 8 --- core/auth.py | 97 +++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 core/auth.py diff --git a/HisabKitab/custom_settings.py b/HisabKitab/custom_settings.py index b8474c5..ae127e5 100644 --- a/HisabKitab/custom_settings.py +++ b/HisabKitab/custom_settings.py @@ -71,7 +71,7 @@ REST_FRAMEWORK = { "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), - "DEFAULT_AUTHENTICATION_CLASSES": ("drfaddons.auth.JSONWebTokenAuthenticationQS",), + "DEFAULT_AUTHENTICATION_CLASSES": ("core.auth.JSONWebTokenAuthenticationQS",), "DEFAULT_PARSER_CLASSES": ("rest_framework.parsers.JSONParser",), "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",), "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", diff --git a/HisabKitab/settings.py b/HisabKitab/settings.py index 0a5e6e8..89d788a 100644 --- a/HisabKitab/settings.py +++ b/HisabKitab/settings.py @@ -11,14 +11,6 @@ """ import os -import django -from django.utils.encoding import smart_str - -django.utils.encoding.smart_text = smart_str -from django.utils.translation import gettext - -django.utils.translation.ugettext = gettext - from .custom_settings import * # Build paths inside the project like this: os.path.join(BASE_DIR, ...) diff --git a/core/auth.py b/core/auth.py new file mode 100644 index 0000000..ed90601 --- /dev/null +++ b/core/auth.py @@ -0,0 +1,97 @@ +from django.conf import settings +from django.utils.encoding import smart_str +from django.utils.translation import gettext as _ +from rest_framework import HTTP_HEADER_ENCODING, exceptions +from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication +from rest_framework_jwt.settings import api_settings +from six import text_type + + +class JSONWebTokenAuthenticationQS(BaseJSONWebTokenAuthentication): + """ + This is a custom JWT Authentication class. This has inherited + BaseJsonWebTokenAuthentication and also used some of the codes from + traditional JSONWebTokenAuthentication class. The traditional one + can only authenticate from Header with a specific key only. + + This model will first look into HEADER and if the key is not found + there, it looks for key in the body. + Key is also changeable and can be set in Django settings as + JWT_AUTH_KEY with default value of Authorization. + + """ + + key = getattr(settings, "JWT_AUTH_KEY", "Authorization") + header_key = "HTTP_" + key.upper() + prefix = api_settings.JWT_AUTH_HEADER_PREFIX + cookie = api_settings.JWT_AUTH_COOKIE + + def get_authorization(self, request): + """ + This function extracts the authorization JWT string. It first + looks for specified key in header and then looks + for the same in body part. + + Parameters + ---------- + request: HttpRequest + This is the raw request that user has sent. + + Returns + ------- + auth: str + Return request's 'JWT_AUTH_KEY:' content from body or + Header, as a bytestring. + + Hide some test client ickyness where the header can be unicode. + """ + + auth = request.META.get(self.header_key, b"") + + if isinstance(auth, text_type): + # Work around django test client oddness + auth = auth.encode(HTTP_HEADER_ENCODING) + return auth + + def get_jwt_value(self, request): + """ + This function has been overloaded and it returns the proper JWT + auth string. + Parameters + ---------- + request: HttpRequest + This is the request that is received by DJango in the view. + Returns + ------- + str + This returns the extracted JWT auth token string. + + """ + + auth = self.get_authorization(request).split() + auth_header_prefix = self.prefix.lower() or "" + + if not auth: + if self.cookie: + return request.COOKIES.get(self.cookie) + return None + + if auth_header_prefix is None or len(auth_header_prefix) < 1: + auth.append("") + auth.reverse() + + if smart_str(auth[0].lower()) != auth_header_prefix: + return None + + if len(auth) == 1: + msg = _("Invalid Authorization header. No credentials provided.") + raise exceptions.AuthenticationFailed(msg) + + elif len(auth) > 2: + msg = _( + "Invalid Authorization header. Credentials string " + "should not contain spaces." + ) + raise exceptions.AuthenticationFailed(msg) + + return auth[1]