@@ -188,6 +188,15 @@ def test_it_should_produce_a_json_web_token_when_valid(self):
188188
189189
190190class TestTokenRefreshSlidingSerializer (TestCase ):
191+ def setUp (self ):
192+ self .username = "test_user"
193+ self .password = "test_password"
194+
195+ self .user = User .objects .create_user (
196+ username = self .username ,
197+ password = self .password ,
198+ )
199+
191200 def test_it_should_not_validate_if_token_invalid (self ):
192201 token = SlidingToken ()
193202 del token ["exp" ]
@@ -269,6 +278,74 @@ def test_it_should_update_token_exp_claim_if_everything_ok(self):
269278
270279 self .assertTrue (old_exp < new_exp )
271280
281+ def test_it_should_raise_error_for_deleted_users (self ):
282+ token = SlidingToken .for_user (self .user )
283+ self .user .delete ()
284+
285+ s = TokenRefreshSlidingSerializer (data = {"token" : str (token )})
286+
287+ # It should raise AuthenticationFailed instead of ObjectDoesNotExist
288+ with self .assertRaises (drf_exceptions .AuthenticationFailed ) as e :
289+ s .is_valid ()
290+
291+ self .assertEqual (e .exception .get_codes (), "no_active_account" )
292+
293+ def test_it_should_raise_error_for_inactive_users (self ):
294+ token = SlidingToken .for_user (self .user )
295+ self .user .is_active = False
296+ self .user .save ()
297+
298+ s = TokenRefreshSlidingSerializer (data = {"token" : str (token )})
299+
300+ with self .assertRaises (drf_exceptions .AuthenticationFailed ) as e :
301+ s .is_valid ()
302+
303+ self .assertEqual (e .exception .get_codes (), "no_active_account" )
304+
305+ @override_api_settings (
306+ CHECK_REVOKE_TOKEN = True ,
307+ REVOKE_TOKEN_CLAIM = "hash_password" ,
308+ BLACKLIST_AFTER_ROTATION = False ,
309+ )
310+ def test_sliding_token_should_fail_after_password_change (self ):
311+ """
312+ Tests that sliding token refresh fails if CHECK_REVOKE_TOKEN is True and the
313+ user's password has changed.
314+ """
315+ token = SlidingToken .for_user (self .user )
316+ self .user .set_password ("new_password" )
317+ self .user .save ()
318+
319+ s = TokenRefreshSlidingSerializer (data = {"token" : str (token )})
320+
321+ with self .assertRaises (drf_exceptions .AuthenticationFailed ) as e :
322+ s .is_valid (raise_exception = True )
323+
324+ self .assertEqual (e .exception .get_codes (), "password_changed" )
325+
326+ @override_api_settings (
327+ CHECK_REVOKE_TOKEN = True ,
328+ REVOKE_TOKEN_CLAIM = "hash_password" ,
329+ BLACKLIST_AFTER_ROTATION = True ,
330+ )
331+ def test_sliding_token_should_blacklist_after_password_change (self ):
332+ """
333+ Tests that if sliding token refresh fails due to a password change, the
334+ offending token is blacklisted.
335+ """
336+ token = SlidingToken .for_user (self .user )
337+ self .user .set_password ("new_password" )
338+ self .user .save ()
339+
340+ s = TokenRefreshSlidingSerializer (data = {"token" : str (token )})
341+ with self .assertRaises (drf_exceptions .AuthenticationFailed ):
342+ s .is_valid (raise_exception = True )
343+
344+ # Check that the token is now in the blacklist
345+ jti = token [api_settings .JTI_CLAIM ]
346+ self .assertTrue (OutstandingToken .objects .filter (jti = jti ).exists ())
347+ self .assertTrue (BlacklistedToken .objects .filter (token__jti = jti ).exists ())
348+
272349
273350class TestTokenRefreshSerializer (TestCase ):
274351 def setUp (self ):
@@ -515,11 +592,6 @@ def test_refresh_token_should_blacklist_after_password_change(self):
515592 Tests that if token refresh fails due to a password change, the
516593 offending refresh token is blacklisted.
517594 """
518- from rest_framework_simplejwt .token_blacklist .models import (
519- BlacklistedToken ,
520- OutstandingToken ,
521- )
522-
523595 refresh = RefreshToken .for_user (self .user )
524596 self .user .set_password ("new_password" )
525597 self .user .save ()
0 commit comments