Skip to content

Commit 58b1874

Browse files
authored
Allow customizing token JSON encoding (#568)
* Allow specifying custom JSONEncoder for TokenBackend * Make TokenBackend JSONEncoder configurable
1 parent 70b8f84 commit 58b1874

4 files changed

Lines changed: 30 additions & 2 deletions

File tree

rest_framework_simplejwt/backends.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import json
12
from datetime import timedelta
2-
from typing import Union
3+
from typing import Optional, Type, Union
34

45
import jwt
56
from django.utils.translation import gettext_lazy as _
@@ -38,6 +39,7 @@ def __init__(
3839
issuer=None,
3940
jwk_url: str = None,
4041
leeway: Union[float, int, timedelta] = None,
42+
json_encoder: Optional[Type[json.JSONEncoder]] = None,
4143
):
4244
self._validate_algorithm(algorithm)
4345

@@ -53,6 +55,7 @@ def __init__(
5355
self.jwks_client = None
5456

5557
self.leeway = leeway
58+
self.json_encoder = json_encoder
5659

5760
def _validate_algorithm(self, algorithm):
5861
"""
@@ -107,7 +110,12 @@ def encode(self, payload):
107110
if self.issuer is not None:
108111
jwt_payload["iss"] = self.issuer
109112

110-
token = jwt.encode(jwt_payload, self.signing_key, algorithm=self.algorithm)
113+
token = jwt.encode(
114+
jwt_payload,
115+
self.signing_key,
116+
algorithm=self.algorithm,
117+
json_encoder=self.json_encoder,
118+
)
111119
if isinstance(token, bytes):
112120
# For PyJWT <= 1.7.1
113121
return token.decode("utf-8")

rest_framework_simplejwt/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"VERIFYING_KEY": "",
2121
"AUDIENCE": None,
2222
"ISSUER": None,
23+
"JSON_ENCODER": None,
2324
"JWK_URL": None,
2425
"LEEWAY": 0,
2526
"AUTH_HEADER_TYPES": ("Bearer",),
@@ -44,6 +45,7 @@
4445

4546
IMPORT_STRINGS = (
4647
"AUTH_TOKEN_CLASSES",
48+
"JSON_ENCODER",
4749
"TOKEN_USER_CLASS",
4850
"USER_AUTHENTICATION_RULE",
4951
)

rest_framework_simplejwt/state.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
api_settings.ISSUER,
1010
api_settings.JWK_URL,
1111
api_settings.LEEWAY,
12+
api_settings.JSON_ENCODER,
1213
)

tests/test_backends.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import uuid
12
from datetime import datetime, timedelta
3+
from json import JSONEncoder
24
from unittest import mock
35
from unittest.mock import patch
46

@@ -34,6 +36,13 @@
3436
IS_OLD_JWT = jwt_version == "1.7.1"
3537

3638

39+
class UUIDJSONEncoder(JSONEncoder):
40+
def default(self, obj):
41+
if isinstance(obj, uuid.UUID):
42+
return str(obj)
43+
return super().default(obj)
44+
45+
3746
class TestTokenBackend(TestCase):
3847
def setUp(self):
3948
self.hmac_token_backend = TokenBackend("HS256", SECRET)
@@ -329,3 +338,11 @@ def test_decode_leeway_hmac_success(self):
329338
self.hmac_leeway_token_backend.decode(expired_token),
330339
self.payload,
331340
)
341+
342+
def test_custom_JSONEncoder(self):
343+
backend = TokenBackend("HS256", SECRET, json_encoder=UUIDJSONEncoder)
344+
unique = uuid.uuid4()
345+
self.payload["uuid"] = unique
346+
token = backend.encode(self.payload)
347+
decoded = backend.decode(token)
348+
self.assertEqual(decoded["uuid"], str(unique))

0 commit comments

Comments
 (0)