@@ -286,10 +286,11 @@ def test_it_should_raise_error_for_deleted_users(self):
286286
287287 s = TokenRefreshSerializer (data = {"refresh" : str (refresh )})
288288
289- with self .assertRaises (django_exceptions .ObjectDoesNotExist ) as e :
289+ # It should raise AuthenticationFailed instead of ObjectDoesNotExist
290+ with self .assertRaises (drf_exceptions .AuthenticationFailed ) as e :
290291 s .is_valid ()
291292
292- self .assertIn ( "does not exist" , str ( e .exception ) )
293+ self .assertEqual ( e .exception . get_codes (), "no_active_account" )
293294
294295 def test_it_should_raise_error_for_inactive_users (self ):
295296 refresh = RefreshToken .for_user (self .user )
@@ -483,6 +484,55 @@ def test_blacklist_app_not_installed_should_pass(self):
483484 reload (tokens )
484485 reload (serializers )
485486
487+ @override_api_settings (
488+ CHECK_REVOKE_TOKEN = True ,
489+ REVOKE_TOKEN_CLAIM = "hash_password" ,
490+ BLACKLIST_AFTER_ROTATION = False ,
491+ )
492+ def test_refresh_token_should_fail_after_password_change (self ):
493+ """
494+ Tests that token refresh fails if CHECK_REVOKE_TOKEN is True and the
495+ user's password has changed.
496+ """
497+ refresh = RefreshToken .for_user (self .user )
498+ self .user .set_password ("new_password" )
499+ self .user .save ()
500+
501+ s = TokenRefreshSerializer (data = {"refresh" : str (refresh )})
502+
503+ with self .assertRaises (drf_exceptions .AuthenticationFailed ) as e :
504+ s .is_valid (raise_exception = True )
505+
506+ self .assertEqual (e .exception .get_codes (), "password_changed" )
507+
508+ @override_api_settings (
509+ CHECK_REVOKE_TOKEN = True ,
510+ REVOKE_TOKEN_CLAIM = "hash_password" ,
511+ BLACKLIST_AFTER_ROTATION = True ,
512+ )
513+ def test_refresh_token_should_blacklist_after_password_change (self ):
514+ """
515+ Tests that if token refresh fails due to a password change, the
516+ offending refresh token is blacklisted.
517+ """
518+ from rest_framework_simplejwt .token_blacklist .models import (
519+ BlacklistedToken ,
520+ OutstandingToken ,
521+ )
522+
523+ refresh = RefreshToken .for_user (self .user )
524+ self .user .set_password ("new_password" )
525+ self .user .save ()
526+
527+ s = TokenRefreshSerializer (data = {"refresh" : str (refresh )})
528+ with self .assertRaises (drf_exceptions .AuthenticationFailed ):
529+ s .is_valid (raise_exception = True )
530+
531+ # Check that the token is now in the blacklist
532+ jti = refresh [api_settings .JTI_CLAIM ]
533+ self .assertTrue (OutstandingToken .objects .filter (jti = jti ).exists ())
534+ self .assertTrue (BlacklistedToken .objects .filter (token__jti = jti ).exists ())
535+
486536
487537class TestTokenVerifySerializer (TestCase ):
488538 def test_it_should_raise_token_error_if_token_invalid (self ):
0 commit comments