Repository: wger-project/wger

Issue:
Add support for JWT
We should add support for Json Web Tokens to access the API

https://github.com/jazzband/djangorestframework-simplejwt


Discussion:
@rolandgeider I would like to implement this
Hi @RohanKaran ! Sure go ahead 

Resolving patch:
diff --git a/wger/core/api/views.py b/wger/core/api/views.py
--- a/wger/core/api/views.py
+++ b/wger/core/api/views.py
@@ -65,7 +65,6 @@
 from wger.utils.api_token import create_token
 from wger.utils.permissions import WgerPermission
 
-
 logger = logging.getLogger(__name__)
 
 
@@ -155,7 +154,7 @@ class ApplicationVersionView(viewsets.ViewSet):
     """
     Returns the application's version
     """
-    permission_classes = (AllowAny, )
+    permission_classes = (AllowAny,)
 
     @staticmethod
     def get(request):
@@ -188,7 +187,7 @@ class RequiredApplicationVersionView(viewsets.ViewSet):
     """
     Returns the minimum required version of flutter app to access this server
     """
-    permission_classes = (AllowAny, )
+    permission_classes = (AllowAny,)
 
     @staticmethod
     def get(request):
@@ -198,6 +197,7 @@ def get(request):
 class UserAPILoginView(viewsets.ViewSet):
     """
     API endpoint for api user objects
+    .. warning:: This endpoint is deprecated
     """
     permission_classes = (AllowAny, )
     queryset = User.objects.all()
@@ -205,7 +205,15 @@ class UserAPILoginView(viewsets.ViewSet):
     throttle_scope = 'login'
 
     def get(self, request):
-        return Response({'message': "You must send a 'username' and 'password' via POST"})
+        return Response(
+            data={
+                'message': "You must send a 'username' and 'password' via POST",
+                'warning': "This endpoint is deprecated."
+            },
+            headers={
+                "Deprecation": "Sat, 01 Oct 2022 23:59:59 GMT",
+            },
+        )
 
     def post(self, request):
         data = request.data
@@ -223,7 +231,13 @@ def post(self, request):
             )
 
         token = create_token(form.get_user())
-        return Response({'token': token.key}, status=status.HTTP_200_OK)
+        return Response(
+            data={'token': token.key, 'message': "This endpoint is deprecated."},
+            status=status.HTTP_200_OK,
+            headers={
+                "Deprecation": "Sat, 01 Oct 2022 23:59:59 GMT",
+            }
+        )
 
 
 class UserAPIRegistrationViewSet(viewsets.ViewSet):
@@ -281,7 +295,7 @@ class DaysOfWeekViewSet(viewsets.ReadOnlyModelViewSet):
     queryset = DaysOfWeek.objects.all()
     serializer_class = DaysOfWeekSerializer
     ordering_fields = '__all__'
-    filterset_fields = ('day_of_week', )
+    filterset_fields = ('day_of_week',)
 
 
 class LicenseViewSet(viewsets.ReadOnlyModelViewSet):
diff --git a/wger/settings_global.py b/wger/settings_global.py
--- a/wger/settings_global.py
+++ b/wger/settings_global.py
@@ -18,7 +18,7 @@
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 import os
 import re
-
+from datetime import timedelta
 
 """
 This file contains the global settings that don't usually need to be changed.
@@ -82,6 +82,7 @@
     'rest_framework',
     'rest_framework.authtoken',
     'django_filters',
+    'rest_framework_simplejwt',
 
     # Breadcrumbs
     'django_bootstrap_breadcrumbs',
@@ -391,6 +392,7 @@
     'DEFAULT_AUTHENTICATION_CLASSES': (
         'rest_framework.authentication.SessionAuthentication',
         'rest_framework.authentication.TokenAuthentication',
+        'rest_framework_simplejwt.authentication.JWTAuthentication',
     ),
     'DEFAULT_FILTER_BACKENDS': (
         'django_filters.rest_framework.DjangoFilterBackend',
@@ -402,6 +404,17 @@
     }
 }
 
+#
+# Django Rest Framework SimpleJWT
+#
+SIMPLE_JWT = {
+    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
+    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
+    'ROTATE_REFRESH_TOKENS': False,
+    'BLACKLIST_AFTER_ROTATION': False,
+    'UPDATE_LAST_LOGIN': False,
+}
+
 #
 # CORS headers: allow all hosts to access the API
 #
diff --git a/wger/urls.py b/wger/urls.py
--- a/wger/urls.py
+++ b/wger/urls.py
@@ -30,6 +30,7 @@
 # Third Party
 from django_email_verification import urls as email_urls
 from rest_framework import routers
+from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView, TokenVerifyView
 
 # wger
 from wger.core.api import views as core_api_views
@@ -43,8 +44,7 @@
 from wger.utils.generic_views import TextTemplateView
 from wger.weight.api import views as weight_api_views
 
-
-#admin.autodiscover()
+# admin.autodiscover()
 
 #
 # REST API
@@ -204,7 +204,7 @@
 # The actual URLs
 #
 urlpatterns = i18n_patterns(
-    #url(r'^admin/', admin.site.urls),
+    # url(r'^admin/', admin.site.urls),
     path('', include(('wger.core.urls', 'core'), namespace='core')),
     path('workout/', include(('wger.manager.urls', 'manager'), namespace='manager')),
     path('exercise/', include(('wger.exercises.urls', 'exercise'), namespace='exercise')),
@@ -244,6 +244,20 @@
         core_api_views.UserAPIRegistrationViewSet.as_view({'post': 'post'}),
         name='api_register'
     ),
+    path(
+        'api/v2/token/',
+        TokenObtainPairView.as_view(),
+        name='token_obtain_pair'
+    ),
+    path(
+        'api/v2/token/refresh/',
+        TokenRefreshView.as_view(),
+        name='token_refresh'
+    ),
+    path(
+        'api/v2/token/verify/',
+        TokenVerifyView.as_view(),
+        name='token_verify'),
 
     # Others
     path(


Test patch: