Skip to content

Commit d77ae20

Browse files
authored
fix: always stringify user_id claim (#887)
* fix: always stringify user_id claim * loose PyJWT requirement
1 parent 890e136 commit d77ae20

File tree

7 files changed

+30
-17
lines changed

7 files changed

+30
-17
lines changed

rest_framework_simplejwt/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ def __str__(self) -> str:
3434
return f"TokenUser {self.id}"
3535

3636
@cached_property
37-
def id(self) -> Union[int, str]:
37+
def id(self) -> str:
3838
return self.token[api_settings.USER_ID_CLAIM]
3939

4040
@cached_property
41-
def pk(self) -> Union[int, str]:
41+
def pk(self) -> str:
4242
return self.id
4343

4444
@cached_property

rest_framework_simplejwt/tokens.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,7 @@ def for_user(cls: type[T], user: AuthUser) -> T:
225225
)
226226

227227
user_id = getattr(user, api_settings.USER_ID_FIELD)
228-
if not isinstance(user_id, int):
229-
user_id = str(user_id)
228+
user_id = str(user_id)
230229

231230
token = cls()
232231
token[api_settings.USER_ID_CLAIM] = user_id

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
install_requires=[
6060
"django>=4.2",
6161
"djangorestframework>=3.14",
62-
"pyjwt>=1.7.1,<2.10.0",
62+
"pyjwt>=1.7.1",
6363
],
6464
python_requires=">=3.9",
6565
extras_require=extras_require,

tests/test_authentication.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ def test_get_user_with_check_revoke_token(self):
225225
# Otherwise, should return correct user
226226
self.assertEqual(self.backend.get_user(payload).id, u.id)
227227

228+
def test_get_user_with_str_user_id_claim(self):
229+
"""
230+
Verify that even though the user id is an int, it can be verified
231+
and retrieved if the user id claim value is a string
232+
"""
233+
234+
user = User.objects.create_user(username="testuser")
235+
payload = {api_settings.USER_ID_CLAIM: str(user.id)}
236+
auth_user = self.backend.get_user(payload)
237+
self.assertEqual(auth_user.id, user.id)
238+
228239

229240
class TestJWTStatelessUserAuthentication(TestCase):
230241
def setUp(self):

tests/test_models.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class TestTokenUser(TestCase):
1313
def setUp(self):
1414
self.token = AuthToken()
15-
self.token[api_settings.USER_ID_CLAIM] = 42
15+
self.token[api_settings.USER_ID_CLAIM] = "42"
1616
self.token["username"] = "deep-thought"
1717
self.token["some_other_stuff"] = "arstarst"
1818

@@ -40,13 +40,13 @@ def test_str(self):
4040
self.assertEqual(str(self.user), "TokenUser 42")
4141

4242
def test_id(self):
43-
self.assertEqual(self.user.id, 42)
43+
self.assertEqual(self.user.id, "42")
4444

4545
def test_pk(self):
46-
self.assertEqual(self.user.pk, 42)
46+
self.assertEqual(self.user.pk, "42")
4747

4848
def test_is_staff(self):
49-
payload = {api_settings.USER_ID_CLAIM: 42}
49+
payload = {api_settings.USER_ID_CLAIM: "42"}
5050
user = TokenUser(payload)
5151

5252
self.assertFalse(user.is_staff)
@@ -57,7 +57,7 @@ def test_is_staff(self):
5757
self.assertTrue(user.is_staff)
5858

5959
def test_is_superuser(self):
60-
payload = {api_settings.USER_ID_CLAIM: 42}
60+
payload = {api_settings.USER_ID_CLAIM: "42"}
6161
user = TokenUser(payload)
6262

6363
self.assertFalse(user.is_superuser)
@@ -68,15 +68,15 @@ def test_is_superuser(self):
6868
self.assertTrue(user.is_superuser)
6969

7070
def test_eq(self):
71-
user1 = TokenUser({api_settings.USER_ID_CLAIM: 1})
72-
user2 = TokenUser({api_settings.USER_ID_CLAIM: 2})
73-
user3 = TokenUser({api_settings.USER_ID_CLAIM: 1})
71+
user1 = TokenUser({api_settings.USER_ID_CLAIM: "1"})
72+
user2 = TokenUser({api_settings.USER_ID_CLAIM: "2"})
73+
user3 = TokenUser({api_settings.USER_ID_CLAIM: "1"})
7474

7575
self.assertNotEqual(user1, user2)
7676
self.assertEqual(user1, user3)
7777

7878
def test_eq_not_implemented(self):
79-
user1 = TokenUser({api_settings.USER_ID_CLAIM: 1})
79+
user1 = TokenUser({api_settings.USER_ID_CLAIM: "1"})
8080
user2 = "user2"
8181

8282
self.assertFalse(user1 == user2)

tests/test_tokens.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,7 @@ def test_for_user(self):
384384
token = MyToken.for_user(self.user)
385385

386386
user_id = getattr(self.user, api_settings.USER_ID_FIELD)
387-
if not isinstance(user_id, int):
388-
user_id = str(user_id)
387+
user_id = str(user_id)
389388

390389
self.assertEqual(token[api_settings.USER_ID_CLAIM], user_id)
391390

@@ -405,6 +404,10 @@ def test_get_token_backend(self):
405404

406405
self.assertEqual(token.get_token_backend(), token_backend)
407406

407+
def test_token_user_id_claim_should_always_be_string(self):
408+
token = MyToken.for_user(self.user)
409+
self.assertIsInstance(token[api_settings.USER_ID_CLAIM], str)
410+
408411

409412
class TestSlidingToken(TestCase):
410413
def test_init(self):

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ deps=
3939
drf314: djangorestframework>=3.14,<3.15
4040
drf315: djangorestframework>=3.15,<3.16
4141
pyjwt171: pyjwt>=1.7.1,<1.8
42-
pyjwt2: pyjwt>=2,<2.10.0
42+
pyjwt2: pyjwt>=2,<3
4343
allowlist_externals=make
4444

4545
[testenv:docs]

0 commit comments

Comments
 (0)