From 655c234a859248c5669b4017f951cfb07de89184 Mon Sep 17 00:00:00 2001 From: Moises Rezonzew Date: Sun, 9 Dec 2018 18:01:32 +0200 Subject: [PATCH 1/7] run renew token only if the token expires --- knox/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knox/auth.py b/knox/auth.py index 4c019b15..0bb2e9e7 100644 --- a/knox/auth.py +++ b/knox/auth.py @@ -74,7 +74,7 @@ def authenticate_credentials(self, token): except (TypeError, binascii.Error): raise exceptions.AuthenticationFailed(msg) if compare_digest(digest, auth_token.digest): - if knox_settings.AUTO_REFRESH: + if knox_settings.AUTO_REFRESH and auth_token.expires: self.renew_token(auth_token) return self.validate_user(auth_token) raise exceptions.AuthenticationFailed(msg) From 91d5e8d6eac49f3f430e6d6295476b5797772bad Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Mon, 17 Dec 2018 18:15:22 +0100 Subject: [PATCH 2/7] Create the UserSerializer context only if needed In LoginView --- knox/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knox/views.py b/knox/views.py index f7c899ea..850758a4 100644 --- a/knox/views.py +++ b/knox/views.py @@ -29,11 +29,11 @@ def post(self, request, format=None): user_logged_in.send(sender=request.user.__class__, request=request, user=request.user) UserSerializer = knox_settings.USER_SERIALIZER - context = {'request': self.request, 'format': self.format_kwarg, 'view': self} if UserSerializer is None: return Response( {'token': token} ) + context = {'request': self.request, 'format': self.format_kwarg, 'view': self} return Response({ 'user': UserSerializer(request.user, context=context).data, 'token': token, From ae8cfd1874880fc87efb3150b938de64137c8152 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Mon, 17 Dec 2018 18:18:32 +0100 Subject: [PATCH 3/7] Make LoginView serializer context overridable --- knox/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/knox/views.py b/knox/views.py index 850758a4..a58bdbb6 100644 --- a/knox/views.py +++ b/knox/views.py @@ -16,6 +16,9 @@ class LoginView(APIView): authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES permission_classes = (IsAuthenticated,) + def get_context(self): + return {'request': self.request, 'format': self.format_kwarg, 'view': self} + def post(self, request, format=None): if knox_settings.TOKEN_LIMIT_PER_USER is not None: now = timezone.now() @@ -33,7 +36,7 @@ def post(self, request, format=None): return Response( {'token': token} ) - context = {'request': self.request, 'format': self.format_kwarg, 'view': self} + context = self.get_context() return Response({ 'user': UserSerializer(request.user, context=context).data, 'token': token, From 392c1e4e5691d2aea998a9588660a83b42592515 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Mon, 17 Dec 2018 18:25:47 +0100 Subject: [PATCH 4/7] Make AuthToken TTL configurable in LoginView We want to set TTL of a token depending on the authentication class. Fix #144 --- knox/views.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/knox/views.py b/knox/views.py index a58bdbb6..6e518c24 100644 --- a/knox/views.py +++ b/knox/views.py @@ -19,6 +19,9 @@ class LoginView(APIView): def get_context(self): return {'request': self.request, 'format': self.format_kwarg, 'view': self} + def get_token_ttl(self): + return knox_settings.TOKEN_TTL + def post(self, request, format=None): if knox_settings.TOKEN_LIMIT_PER_USER is not None: now = timezone.now() @@ -28,7 +31,8 @@ def post(self, request, format=None): {"error": "Maximum amount of tokens allowed per user exceeded."}, status=status.HTTP_403_FORBIDDEN ) - token = AuthToken.objects.create(request.user) + token_ttl = self.get_token_ttl() + token = AuthToken.objects.create(request.user, token_ttl) user_logged_in.send(sender=request.user.__class__, request=request, user=request.user) UserSerializer = knox_settings.USER_SERIALIZER From 0e6656c30cf8d7bfa271b0dff7c0c6ca99e76d51 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Thu, 20 Dec 2018 18:00:08 +0100 Subject: [PATCH 5/7] Make AuthToken per user configurable in LoginView We want to limit the number of token available per user depending on the authentication class. --- knox/views.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/knox/views.py b/knox/views.py index 6e518c24..db464a74 100644 --- a/knox/views.py +++ b/knox/views.py @@ -22,11 +22,15 @@ def get_context(self): def get_token_ttl(self): return knox_settings.TOKEN_TTL + def get_token_limit_per_user(self): + return knox_settings.TOKEN_LIMIT_PER_USER + def post(self, request, format=None): - if knox_settings.TOKEN_LIMIT_PER_USER is not None: + token_limit_per_user = self.get_token_limit_per_user() + if token_limit_per_user is not None: now = timezone.now() token = request.user.auth_token_set.filter(expires__gt=now) - if token.count() >= knox_settings.TOKEN_LIMIT_PER_USER: + if token.count() >= token_limit_per_user: return Response( {"error": "Maximum amount of tokens allowed per user exceeded."}, status=status.HTTP_403_FORBIDDEN From f461f66e312da6bfd42c8e35bb163bf60259db54 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Thu, 20 Dec 2018 18:11:07 +0100 Subject: [PATCH 6/7] Update docs for LoginView updates Add changelog and documentation in views. --- CHANGELOG.md | 6 ++++++ docs/changes.md | 4 ++++ docs/views.md | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6ef7b5..9717435e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +3.5.0 +===== + +- The context, token TTL and tokens per user settings in `LoginView` are now dynamic + + 3.4.0 ===== diff --git a/docs/changes.md b/docs/changes.md index d71937a5..c9149bb0 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,5 +1,9 @@ # Changelog +## 3.5.0 + +- The context, token TTL and tokens per user settings in `LoginView` are now dynamic + ## 3.4.0 Our release cycle was broken since 3.1.5, hence you can not find the previous releases on pypi. We now fixed the problem. diff --git a/docs/views.md b/docs/views.md index 9dbdb521..f313cf27 100644 --- a/docs/views.md +++ b/docs/views.md @@ -13,6 +13,12 @@ schemes. If you would like to use a different authentication scheme to the default, you can extend this class to provide your own value for `authentication_classes` +It is possible to customize LoginView behaviour by overriding the following +helper methods: +- `get_context`, to change the context passed to the `UserSerializer` +- `get_token_ttl`, to change the token ttl +- `get_token_limit_per_user`, to change the number of tokens available for a user + --- When the endpoint authenticates a request, a json object will be returned containing the `token` key along with the actual value for the key by default. @@ -22,8 +28,8 @@ containing the `token` key along with the actual value for the key by default. If you wish to return custom data upon successful authentication like `first_name`, `last_name`, and `username` then the included `UserSerializer` class can be used inside `REST_KNOX` settings by adding `knox.serializers.UserSerializer` ---- +--- Obviously, if your app uses a custom user model that does not have these fields, a custom serializer must be used. From bea0133372117e77435e414da7335b0fedc1d960 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Thu, 20 Dec 2018 20:03:38 +0100 Subject: [PATCH 7/7] Bump version to 3.5.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 10bd3640..71b7eab0 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='3.4.0', + version='3.5.0', description='Authentication for django rest framework', long_description=long_description, long_description_content_type='text/markdown',