test_tokens.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. from datetime import datetime, timedelta
  2. from django.conf import settings
  3. from django.contrib.auth.models import User
  4. from django.contrib.auth.tokens import PasswordResetTokenGenerator
  5. from django.test import TestCase
  6. class MockedPasswordResetTokenGenerator(PasswordResetTokenGenerator):
  7. def __init__(self, now):
  8. self._now_val = now
  9. def _now(self):
  10. return self._now_val
  11. class TokenGeneratorTest(TestCase):
  12. def test_make_token(self):
  13. user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
  14. p0 = PasswordResetTokenGenerator()
  15. tk1 = p0.make_token(user)
  16. self.assertIs(p0.check_token(user, tk1), True)
  17. def test_10265(self):
  18. """
  19. The token generated for a user created in the same request
  20. will work correctly.
  21. """
  22. user = User.objects.create_user('comebackkid', 'test3@example.com', 'testpw')
  23. user_reload = User.objects.get(username='comebackkid')
  24. p0 = MockedPasswordResetTokenGenerator(datetime.now())
  25. tk1 = p0.make_token(user)
  26. tk2 = p0.make_token(user_reload)
  27. self.assertEqual(tk1, tk2)
  28. def test_timeout(self):
  29. """The token is valid after n seconds, but no greater."""
  30. # Uses a mocked version of PasswordResetTokenGenerator so we can change
  31. # the value of 'now'.
  32. user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
  33. p0 = PasswordResetTokenGenerator()
  34. tk1 = p0.make_token(user)
  35. p1 = MockedPasswordResetTokenGenerator(
  36. datetime.now() + timedelta(seconds=settings.PASSWORD_RESET_TIMEOUT)
  37. )
  38. self.assertIs(p1.check_token(user, tk1), True)
  39. p2 = MockedPasswordResetTokenGenerator(
  40. datetime.now() + timedelta(seconds=(settings.PASSWORD_RESET_TIMEOUT + 1))
  41. )
  42. self.assertIs(p2.check_token(user, tk1), False)
  43. with self.settings(PASSWORD_RESET_TIMEOUT=60 * 60):
  44. p3 = MockedPasswordResetTokenGenerator(
  45. datetime.now() + timedelta(seconds=settings.PASSWORD_RESET_TIMEOUT)
  46. )
  47. self.assertIs(p3.check_token(user, tk1), True)
  48. p4 = MockedPasswordResetTokenGenerator(
  49. datetime.now() + timedelta(seconds=(settings.PASSWORD_RESET_TIMEOUT + 1))
  50. )
  51. self.assertIs(p4.check_token(user, tk1), False)
  52. def test_check_token_with_nonexistent_token_and_user(self):
  53. user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
  54. p0 = PasswordResetTokenGenerator()
  55. tk1 = p0.make_token(user)
  56. self.assertIs(p0.check_token(None, tk1), False)
  57. self.assertIs(p0.check_token(user, None), False)
  58. def test_token_with_different_secret(self):
  59. """
  60. A valid token can be created with a secret other than SECRET_KEY by
  61. using the PasswordResetTokenGenerator.secret attribute.
  62. """
  63. user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
  64. new_secret = 'abcdefghijkl'
  65. # Create and check a token with a different secret.
  66. p0 = PasswordResetTokenGenerator()
  67. p0.secret = new_secret
  68. tk0 = p0.make_token(user)
  69. self.assertIs(p0.check_token(user, tk0), True)
  70. # Create and check a token with the default secret.
  71. p1 = PasswordResetTokenGenerator()
  72. self.assertEqual(p1.secret, settings.SECRET_KEY)
  73. self.assertNotEqual(p1.secret, new_secret)
  74. tk1 = p1.make_token(user)
  75. # Tokens created with a different secret don't validate.
  76. self.assertIs(p0.check_token(user, tk1), False)
  77. self.assertIs(p1.check_token(user, tk0), False)
  78. def test_legacy_token_validation(self):
  79. # RemovedInDjango40Warning: pre-Django 3.1 tokens will be invalid.
  80. user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
  81. p_old_generator = PasswordResetTokenGenerator()
  82. p_old_generator.algorithm = 'sha1'
  83. p_new_generator = PasswordResetTokenGenerator()
  84. legacy_token = p_old_generator.make_token(user)
  85. self.assertIs(p_old_generator.check_token(user, legacy_token), True)
  86. self.assertIs(p_new_generator.check_token(user, legacy_token), True)