dj-jwt-auth 1.6.0__tar.gz → 1.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/PKG-INFO +6 -1
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/dj_jwt_auth.egg-info/PKG-INFO +6 -1
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/config.py +4 -1
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/exceptions.py +6 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/middleware.py +3 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/user.py +7 -7
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/setup.cfg +2 -1
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/tests/test.py +24 -4
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/MANIFEST.in +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/README.md +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/dj_jwt_auth.egg-info/SOURCES.txt +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/dj_jwt_auth.egg-info/dependency_links.txt +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/dj_jwt_auth.egg-info/requires.txt +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/dj_jwt_auth.egg-info/top_level.txt +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/__init__.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/pkce.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/roles.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/settings.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/templates/admin/login.html +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/templates/django-jwt-index.html +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/urls.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/utils.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/django_jwt/views.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/pyproject.toml +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/setup.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/tests/__init__.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/tests/models.py +0 -0
- {dj-jwt-auth-1.6.0 → dj_jwt_auth-1.7.1}/tests/urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dj-jwt-auth
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: A Django package for JSON Web Token validation and verification. Using PyJWT.
|
|
5
5
|
Home-page: https://www.example.com/
|
|
6
6
|
Author: Konstantin Seleznev
|
|
@@ -17,10 +17,15 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.9
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
21
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
21
22
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
22
23
|
Requires-Python: >=3.8
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: Django>=3.0
|
|
26
|
+
Requires-Dist: pyjwt>=2.5.0
|
|
27
|
+
Requires-Dist: requests>=2.28.1
|
|
28
|
+
Requires-Dist: cryptography>=36.0.2
|
|
24
29
|
|
|
25
30
|
# Django-JWT
|
|
26
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dj-jwt-auth
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: A Django package for JSON Web Token validation and verification. Using PyJWT.
|
|
5
5
|
Home-page: https://www.example.com/
|
|
6
6
|
Author: Konstantin Seleznev
|
|
@@ -17,10 +17,15 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.9
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
21
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
21
22
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
22
23
|
Requires-Python: >=3.8
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: Django>=3.0
|
|
26
|
+
Requires-Dist: pyjwt>=2.5.0
|
|
27
|
+
Requires-Dist: requests>=2.28.1
|
|
28
|
+
Requires-Dist: cryptography>=36.0.2
|
|
24
29
|
|
|
25
30
|
# Django-JWT
|
|
26
31
|
|
|
@@ -6,7 +6,7 @@ import requests
|
|
|
6
6
|
from jwt.algorithms import ECAlgorithm, RSAAlgorithm
|
|
7
7
|
|
|
8
8
|
from django_jwt import settings
|
|
9
|
-
from django_jwt.exceptions import ConfigException
|
|
9
|
+
from django_jwt.exceptions import AlgorithmNotSupportedException, ConfigException
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def ensure_well_known(url: str) -> str:
|
|
@@ -24,6 +24,9 @@ class Config:
|
|
|
24
24
|
if not self.route:
|
|
25
25
|
raise ConfigException("OIDC_CONFIG_ROUTES is not set")
|
|
26
26
|
|
|
27
|
+
if alg not in self.route:
|
|
28
|
+
raise AlgorithmNotSupportedException(f"Algorithm {alg} is not supported")
|
|
29
|
+
|
|
27
30
|
response = requests.get(ensure_well_known(self.route[alg]))
|
|
28
31
|
response.raise_for_status()
|
|
29
32
|
return response.json()
|
|
@@ -5,6 +5,7 @@ from django.http import JsonResponse
|
|
|
5
5
|
from django.utils.deprecation import MiddlewareMixin
|
|
6
6
|
from jwt import ExpiredSignatureError
|
|
7
7
|
|
|
8
|
+
from django_jwt.exceptions import AlgorithmNotSupportedException
|
|
8
9
|
from django_jwt.user import UserHandler
|
|
9
10
|
from django_jwt.utils import oidc_handler
|
|
10
11
|
|
|
@@ -27,6 +28,8 @@ class JWTAuthMiddleware(MiddlewareMixin):
|
|
|
27
28
|
try:
|
|
28
29
|
info = oidc_handler.decode_token(raw_token)
|
|
29
30
|
request.user = request._cached_user = UserHandler(info, request, raw_token).get_user()
|
|
31
|
+
except AlgorithmNotSupportedException as exc:
|
|
32
|
+
return JsonResponse(status=HTTPStatus.UNAUTHORIZED.value, data={"detail": str(exc)})
|
|
30
33
|
except ExpiredSignatureError:
|
|
31
34
|
return JsonResponse(status=HTTPStatus.UNAUTHORIZED.value, data={"detail": "expired token"})
|
|
32
35
|
except UnicodeDecodeError as exc:
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
from datetime import datetime
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
2
|
from functools import cache
|
|
3
3
|
from logging import getLogger
|
|
4
4
|
|
|
5
|
-
import pytz
|
|
6
5
|
from django.contrib.auth import get_user_model
|
|
7
6
|
from django.contrib.auth.models import Group, Permission
|
|
8
7
|
from django.http.request import HttpRequest
|
|
@@ -10,7 +9,7 @@ from django.http.request import HttpRequest
|
|
|
10
9
|
from django_jwt import settings
|
|
11
10
|
from django_jwt.utils import oidc_handler
|
|
12
11
|
|
|
13
|
-
utc =
|
|
12
|
+
utc = timezone.utc
|
|
14
13
|
log = getLogger(__name__)
|
|
15
14
|
|
|
16
15
|
model = get_user_model()
|
|
@@ -32,7 +31,7 @@ class UserHandler:
|
|
|
32
31
|
|
|
33
32
|
modified_at = payload.get(settings.OIDC_TOKEN_MODIFIED_FIELD, None)
|
|
34
33
|
if modified_at and isinstance(modified_at, int):
|
|
35
|
-
self.modified_at =
|
|
34
|
+
self.modified_at = datetime.fromtimestamp(modified_at, utc)
|
|
36
35
|
|
|
37
36
|
self.on_create = settings.OIDC_USER_ON_CREATE
|
|
38
37
|
self.on_update = settings.OIDC_USER_ON_UPDATE
|
|
@@ -61,8 +60,9 @@ class UserHandler:
|
|
|
61
60
|
def _create_new_user(self) -> model:
|
|
62
61
|
"""Create new user if user is not found in database even by email."""
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
email = self.kwargs.pop("email")
|
|
64
|
+
user, created = model.objects.get_or_create(email=email, defaults=self.kwargs)
|
|
65
|
+
if created and self.on_create:
|
|
66
66
|
self.on_create(user, self.request, self.payload)
|
|
67
67
|
return user
|
|
68
68
|
|
|
@@ -81,7 +81,7 @@ class UserHandler:
|
|
|
81
81
|
user_modified_at = getattr(user, settings.OIDC_USER_MODIFIED_FIELD, None)
|
|
82
82
|
if user_modified_at:
|
|
83
83
|
if not user_modified_at.tzinfo:
|
|
84
|
-
user_modified_at =
|
|
84
|
+
user_modified_at = user_modified_at.replace(tzinfo=utc)
|
|
85
85
|
is_modified = user_modified_at < self.modified_at
|
|
86
86
|
|
|
87
87
|
log.info(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = dj-jwt-auth
|
|
3
|
-
version = 1.
|
|
3
|
+
version = 1.7.1
|
|
4
4
|
description = A Django package for JSON Web Token validation and verification. Using PyJWT.
|
|
5
5
|
long_description = file: README.md
|
|
6
6
|
url = https://www.example.com/
|
|
@@ -19,6 +19,7 @@ classifiers =
|
|
|
19
19
|
Programming Language :: Python :: 3.9
|
|
20
20
|
Programming Language :: Python :: 3.10
|
|
21
21
|
Programming Language :: Python :: 3.11
|
|
22
|
+
Programming Language :: Python :: 3.12
|
|
22
23
|
Topic :: Internet :: WWW/HTTP
|
|
23
24
|
Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
24
25
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
from datetime import datetime
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
2
|
from http import HTTPStatus
|
|
3
3
|
from unittest.mock import Mock, patch
|
|
4
4
|
|
|
5
|
-
import pytz
|
|
6
5
|
from django.contrib.auth import get_user_model
|
|
7
6
|
from django.contrib.auth.models import Group, Permission
|
|
8
7
|
from django.test import TestCase
|
|
@@ -10,11 +9,13 @@ from django.urls import reverse
|
|
|
10
9
|
from jwt.api_jwt import ExpiredSignatureError
|
|
11
10
|
|
|
12
11
|
from django_jwt import settings
|
|
12
|
+
from django_jwt.config import config
|
|
13
|
+
from django_jwt.exceptions import ConfigException
|
|
13
14
|
from django_jwt.middleware import JWTAuthMiddleware
|
|
14
15
|
from django_jwt.roles import ROLE
|
|
15
16
|
from django_jwt.user import role_handler
|
|
16
17
|
|
|
17
|
-
utc =
|
|
18
|
+
utc = timezone.utc
|
|
18
19
|
access_token_payload = {
|
|
19
20
|
"sub": "1234",
|
|
20
21
|
"updated_at": 2687276498,
|
|
@@ -185,7 +186,7 @@ class OIDCHandlerTest(TestCase):
|
|
|
185
186
|
- don't call userdata if updated_at is not changed
|
|
186
187
|
"""
|
|
187
188
|
|
|
188
|
-
updated_at =
|
|
189
|
+
updated_at = datetime.fromtimestamp(access_token_payload["updated_at"], utc)
|
|
189
190
|
user = User.objects.create(kc_id="1234", first_name="", last_name="", username="")
|
|
190
191
|
|
|
191
192
|
self.middleware.process_request(self.request)
|
|
@@ -201,6 +202,25 @@ class OIDCHandlerTest(TestCase):
|
|
|
201
202
|
# self.assertEqual(user_info.call_count, 1)
|
|
202
203
|
|
|
203
204
|
|
|
205
|
+
@patch("django_jwt.utils.get_alg", return_value="HS256")
|
|
206
|
+
class ConfigTest(TestCase):
|
|
207
|
+
def setUp(self):
|
|
208
|
+
self.middleware = JWTAuthMiddleware(get_response=lambda x: x)
|
|
209
|
+
self.request = Mock()
|
|
210
|
+
self.request.META = {"HTTP_AUTHORIZATION": "Bearer Token"}
|
|
211
|
+
|
|
212
|
+
@patch.object(config, "route", {})
|
|
213
|
+
def test_empty_routes(self, *_):
|
|
214
|
+
with self.assertRaises(ConfigException):
|
|
215
|
+
self.middleware.process_request(self.request)
|
|
216
|
+
|
|
217
|
+
@patch.object(config, "route", {"ES256": "http://localhost:8080"})
|
|
218
|
+
def test_not_supported_alg(self, *_):
|
|
219
|
+
response = self.middleware.process_request(self.request)
|
|
220
|
+
self.assertEqual(HTTPStatus.UNAUTHORIZED.value, response.status_code)
|
|
221
|
+
self.assertEqual(b'{"detail": "Algorithm HS256 is not supported"}', response.content)
|
|
222
|
+
|
|
223
|
+
|
|
204
224
|
class RolesTest(TestCase):
|
|
205
225
|
def setUp(self) -> None:
|
|
206
226
|
self.user = User.objects.create(username="user")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|