diff --git a/demo/demo/settings.py b/demo/demo/settings.py index 4496f0d..03de0a1 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -123,7 +123,7 @@ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', - 'dj_rest_auth.utils.JWTCookieAuthentication' + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication' ), 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' } diff --git a/dev-requirements.txt b/dev-requirements.txt index 73b9db0..8ecc9c6 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,4 +2,5 @@ responses>=0.5.0 djangorestframework-simplejwt==4.4.0 django-allauth>=0.25.0 -coveralls>=1.11.1 \ No newline at end of file +coveralls>=1.11.1 +unittest-xml-reporting>=3.0.2 \ No newline at end of file diff --git a/dj_rest_auth/jwt_auth.py b/dj_rest_auth/jwt_auth.py new file mode 100644 index 0000000..39f9c78 --- /dev/null +++ b/dj_rest_auth/jwt_auth.py @@ -0,0 +1,27 @@ +from django.conf import settings +from rest_framework_simplejwt.authentication import JWTAuthentication + + +class JWTCookieAuthentication(JWTAuthentication): + """ + An authentication plugin that hopefully authenticates requests through a JSON web + token provided in a request cookie (and through the header as normal, with a + preference to the header). + """ + + def authenticate(self, request): + cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) + header = self.get_header(request) + if header is None: + if cookie_name: + raw_token = request.COOKIES.get(cookie_name) + else: + return None + else: + raw_token = self.get_raw_token(header) + + if raw_token is None: + return None + + validated_token = self.get_validated_token(raw_token) + return self.get_user(validated_token), validated_token diff --git a/dj_rest_auth/tests/settings.py b/dj_rest_auth/tests/settings.py index 56f0e94..e038c45 100644 --- a/dj_rest_auth/tests/settings.py +++ b/dj_rest_auth/tests/settings.py @@ -68,7 +68,7 @@ TEMPLATES = [ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'dj_rest_auth.utils.JWTCookieAuthentication', + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication', ) } diff --git a/dj_rest_auth/tests/test_api.py b/dj_rest_auth/tests/test_api.py index f25f5fc..3c1ff0e 100644 --- a/dj_rest_auth/tests/test_api.py +++ b/dj_rest_auth/tests/test_api.py @@ -563,7 +563,7 @@ class APIBasicTests(TestsMixin, TestCase): @override_settings(JWT_AUTH_COOKIE='jwt-auth') @override_settings(REST_FRAMEWORK=dict( DEFAULT_AUTHENTICATION_CLASSES=[ - 'dj_rest_auth.utils.JWTCookieAuthentication' + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication' ] )) @override_settings(REST_SESSION_LOGIN=False) @@ -624,7 +624,7 @@ class APIBasicTests(TestsMixin, TestCase): @override_settings(JWT_AUTH_COOKIE=None) @override_settings(REST_FRAMEWORK=dict( DEFAULT_AUTHENTICATION_CLASSES=[ - 'dj_rest_auth.utils.JWTCookieAuthentication' + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication' ] )) @override_settings(REST_SESSION_LOGIN=False) @@ -649,7 +649,7 @@ class APIBasicTests(TestsMixin, TestCase): @override_settings(JWT_AUTH_COOKIE='jwt-auth') @override_settings(REST_FRAMEWORK=dict( DEFAULT_AUTHENTICATION_CLASSES=[ - 'dj_rest_auth.utils.JWTCookieAuthentication' + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication' ] )) @override_settings(REST_SESSION_LOGIN=False) diff --git a/dj_rest_auth/utils.py b/dj_rest_auth/utils.py index fa971de..7011c8a 100644 --- a/dj_rest_auth/utils.py +++ b/dj_rest_auth/utils.py @@ -1,5 +1,7 @@ from importlib import import_module +from django.conf import settings + def import_callable(path_or_callable): if hasattr(path_or_callable, '__call__'): @@ -15,38 +17,14 @@ def default_create_token(token_model, user, serializer): return token -try: - from django.conf import settings - from rest_framework_simplejwt.authentication import JWTAuthentication +def jwt_encode(user): from rest_framework_simplejwt.serializers import TokenObtainPairSerializer + TOPS = import_callable(getattr(settings, 'JWT_TOKEN_CLAIMS_SERIALIZER', TokenObtainPairSerializer)) + refresh = TOPS.get_token(user) + return refresh.access_token, refresh - def jwt_encode(user): - TOPS = import_callable(getattr(settings, 'JWT_TOKEN_CLAIMS_SERIALIZER', TokenObtainPairSerializer)) - refresh = TOPS.get_token(user) - return refresh.access_token, refresh - - class JWTCookieAuthentication(JWTAuthentication): - """ - An authentication plugin that hopefully authenticates requests through a JSON web - token provided in a request cookie (and through the header as normal, with a - preference to the header). - """ - def authenticate(self, request): - cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None) - header = self.get_header(request) - if header is None: - if cookie_name: - raw_token = request.COOKIES.get(cookie_name) - else: - return None - else: - raw_token = self.get_raw_token(header) - - if raw_token is None: - return None - - validated_token = self.get_validated_token(raw_token) - return self.get_user(validated_token), validated_token +try: + from .jwt_auth import JWTCookieAuthentication except ImportError: - raise ImportError("rest-framework-simplejwt needs to be installed") + pass diff --git a/docs/installation.rst b/docs/installation.rst index 94579ee..95de78f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -35,9 +35,9 @@ Installation .. code-block:: python - python manage.py migrate - - + python manage.py migrate + + You're good to go now! @@ -59,7 +59,7 @@ Registration (optional) 'allauth.account', 'dj_rest_auth.registration', ) - + SITE_ID = 1 3. Add dj_rest_auth.registration urls: @@ -76,7 +76,7 @@ Registration (optional) Social Authentication (optional) -------------------------------- -Using ``django-allauth``, ``dj-rest-auth`` provides helpful class for creating social media authentication view. +Using ``django-allauth``, ``dj-rest-auth`` provides helpful class for creating social media authentication view. .. note:: Points 1 and 2 are related to ``django-allauth`` configuration, so if you have already configured social authentication, then please go to step 3. See ``django-allauth`` documentation for more details. @@ -223,7 +223,7 @@ In urls.py: You can also use the following views to check all social accounts attached to the current authenticated user and disconnect selected social accounts: .. code-block:: python - + from dj_rest_auth.registration.views import ( SocialAccountListView, SocialAccountDisconnectView ) @@ -259,7 +259,7 @@ By default ``dj-rest-auth`` uses Django's Token-based authentication. If you wan ... 'DEFAULT_AUTHENTICATION_CLASSES': ( ... - 'dj_rest_auth.utils.JWTCookieAuthentication', + 'dj_rest_auth.jwt_auth.JWTCookieAuthentication', ) ... }