Skip to content

Commit 49b84ed

Browse files
committed
Fix user_id type mismatch when user claim is not pk
Regarding changes made at https://github.com/jazzband/djangorestframework-simplejwt/pull/806/files We're using a USER_ID_CLAIM that is neither the primary key field nor is it the same type as the primary key, and these previous changes fail at this point when attempting to create an OutstandingToken, because it assumes that the ID pulled out of the token claims is usable as the database key for a user. So to mitigate this gets the user from the database using the USER_ID_FIELD setting and uses that in the get_or_create call. Also include a test of handling the case where the user is deleted when the token is blacklisted.
1 parent cb00a8b commit 49b84ed

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

rest_framework_simplejwt/tokens.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from uuid import uuid4
44

55
from django.conf import settings
6+
from django.contrib.auth import get_user_model
67
from django.contrib.auth.models import AbstractBaseUser
78
from django.utils.module_loading import import_string
89
from django.utils.translation import gettext_lazy as _
@@ -266,12 +267,17 @@ def blacklist(self) -> BlacklistedToken:
266267
jti = self.payload[api_settings.JTI_CLAIM]
267268
exp = self.payload["exp"]
268269
user_id = self.payload.get(api_settings.USER_ID_CLAIM)
270+
User = get_user_model()
271+
try:
272+
user = User.objects.get(**{api_settings.USER_ID_FIELD: user_id})
273+
except User.DoesNotExist:
274+
user = None
269275

270276
# Ensure outstanding token exists with given jti
271277
token, _ = OutstandingToken.objects.get_or_create(
272278
jti=jti,
273279
defaults={
274-
"user_id": user_id,
280+
"user": user,
275281
"created_at": self.current_time,
276282
"token": str(self),
277283
"expires_at": datetime_from_epoch(exp),

tests/test_token_blacklist.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from django.db.models import BigAutoField
77
from django.test import TestCase
88
from django.utils import timezone
9-
109
from rest_framework_simplejwt.exceptions import TokenError
1110
from rest_framework_simplejwt.serializers import TokenVerifySerializer
1211
from rest_framework_simplejwt.settings import api_settings
@@ -160,6 +159,35 @@ def test_outstanding_token_and_blacklisted_token_user(self):
160159
outstanding_token = OutstandingToken.objects.get(token=token)
161160
self.assertEqual(outstanding_token.user, self.user)
162161

162+
@override_api_settings(USER_ID_FIELD="email", USER_ID_CLAIM="email")
163+
def test_outstanding_token_and_blacklisted_token_created_at_with_modified_user_id_field(
164+
self,
165+
):
166+
token = RefreshToken.for_user(self.user)
167+
168+
token.blacklist()
169+
outstanding_token = OutstandingToken.objects.get(token=token)
170+
self.assertEqual(outstanding_token.created_at, token.current_time)
171+
172+
@override_api_settings(USER_ID_FIELD="email", USER_ID_CLAIM="email")
173+
def test_outstanding_token_and_blacklisted_token_user_with_modifed_user_id_field(
174+
self,
175+
):
176+
token = RefreshToken.for_user(self.user)
177+
178+
token.blacklist()
179+
outstanding_token = OutstandingToken.objects.get(token=token)
180+
self.assertEqual(outstanding_token.user, self.user)
181+
182+
183+
@override_api_settings(USER_ID_FIELD="email", USER_ID_CLAIM="email")
184+
def test_outstanding_token_with_deleted_user_and_modifed_user_id_field(self):
185+
self.assertFalse(BlacklistedToken.objects.exists())
186+
token = RefreshToken.for_user(self.user)
187+
self.user.delete()
188+
token.blacklist()
189+
self.assertTrue(BlacklistedToken.objects.count(), 1)
190+
163191

164192
class TestTokenBlacklistFlushExpiredTokens(TestCase):
165193
def setUp(self):

0 commit comments

Comments
 (0)