예제 #1
0
    def test_primary_key_and_timestamp_confusion(self):
        """Token signature changes if SESAME_MAX_AGE is enabled or disabled."""
        TIME = TIMESTAMP_OFFSET + (1 << 24)
        user1 = self.user
        with override_settings(SESAME_MAX_AGE=300):
            with unittest.mock.patch("time.time", return_value=TIME):
                token1 = create_token(user1)

        with override_settings(AUTH_USER_MODEL="tests.BigAutoUser"):
            user2 = self.create_user("jane", pk=(user1.pk << 32) + (1 << 24))
            token2 = create_token(user2)
            # Duplicate user1 in the BigAutoUser table.
            user1.__class__ = user2.__class__
            user1.save()

        # The first 8 bytes are the same:
        # - token1: primary key of user1 and timestamp
        # - token2: primary key of user2
        self.assertEqual(
            self.decode_token(token1)[:8],
            self.decode_token(token2)[:8])

        with override_settings(AUTH_USER_MODEL="tests.BigAutoUser"):
            user = parse_token(token1, self.get_user)
        self.assertIsNone(user)
        self.assertLogsContain("Invalid token for user jane")

        with override_settings(SESAME_MAX_AGE=300):
            with unittest.mock.patch("time.time", return_value=TIME + 1):
                user = parse_token(token2, self.get_user)
        self.assertIsNone(user)
        self.assertLogsContain("Invalid token for user john in default scope")
예제 #2
0
    def test_packer_confusion(self):
        """Token signature changes if SESAME_PACKER changes."""
        user1 = self.user
        with override_settings(
                SESAME_PACKER="tests.test_packers.RepeatPacker"):
            token1 = create_token(user1)
        user2 = self.create_user("jane", pk=(user1.pk << 16) + user1.pk)
        token2 = create_token(user2)

        # The first 4 bytes are the same:
        # - token1: primary key of user1 encoded with RepeatPacker
        # - token2: primary key of user2
        self.assertEqual(
            self.decode_token(token1)[:4],
            self.decode_token(token2)[:4])

        user = parse_token(token1, self.get_user)
        self.assertIsNone(user)
        self.assertLogsContain("Invalid token for user jane")

        with override_settings(
                SESAME_PACKER="tests.test_packers.RepeatPacker"):
            user = parse_token(token2, self.get_user)
        self.assertIsNone(user)
        self.assertLogsContain("Invalid token for user john in default scope")
예제 #3
0
 def test_custom_max_age_ignored(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user, max_age=-300)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Ignoring max_age argument")
     self.assertLogsContain("Valid token for user john")
예제 #4
0
 def test_custom_max_age_timedelta(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     max_age = datetime.timedelta(seconds=300)
     user = parse_token(token, self.get_user, max_age=max_age)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Valid token for user john")
예제 #5
0
 def test_valid_token_after_password_change(self):
     token = create_token(self.user)
     self.user.set_password("hunter2")
     self.user.save()
     user = parse_token(token, self.get_user)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Valid token for user john in default scope")
예제 #6
0
 def test_one_time_token_invalidation_when_last_login_date_changes(self):
     token = create_token(self.user)
     self.user.last_login = timezone.now() - datetime.timedelta(1800)
     self.user.save()
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Invalid token for user john in default scope")
예제 #7
0
 def test_token_with_timestamp(self):
     with override_settings(SESAME_MAX_AGE=300):
         token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot extract signature")
예제 #8
0
 def test_extended_max_age_token(self):
     token = create_token(self.user)
     with override_settings(SESAME_MAX_AGE=300):
         self.assertTrue(detect_token(token))
         user = parse_token(token, self.get_user)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Valid token for user john in default scope")
예제 #9
0
 def test_custom_packer_change(self):
     token = create_token(self.user)
     with override_settings(
             SESAME_PACKER="tests.test_packers.RepeatPacker"):
         user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot extract primary key")
예제 #10
0
 def test_key_change_invalidates_tokens(self):
     """Token signature changes if SESAME_KEY changes."""
     token = create_token(self.user)
     with override_settings(SESAME_KEY="new"):
         user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Invalid token for user john in default scope")
예제 #11
0
 def test_invalid_token_after_password_change(self):
     token = create_token(self.user)
     self.user.set_password("hunter2")
     self.user.save()
     user = parse_token(token, self.get_user)
     self.assertEqual(user, None)
     self.assertLogsContain("Invalid token for user john")
예제 #12
0
 def test_random_token(self):
     token = "!@#$" * 6
     self.assertEqual(len(token), len(create_token(self.user)))
     self.assertFalse(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token")
예제 #13
0
 def test_unknown_user(self):
     token = create_token(self.user)
     self.user.delete()
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Unknown or inactive user: pk = 1")
예제 #14
0
    def test_naive_token_hijacking_fails(self):
        # The revocation key may be identical for two users:
        # - if SESAME_INVALIDATE_ON_PASSWORD_CHANGE is False or if they don't
        #   have a password;
        # - if SESAME_ONE_TIME is False, which is the default, or if they have
        #   the same last_login.
        # In that case, could one user could impersonate the other?
        user1 = self.user
        user2 = self.create_user("jane")

        token1 = create_token(user1)
        token2 = create_token(user2)

        # Check that the test scenario produces identical revocation keys.
        self.assertEqual(get_revocation_key(user1), get_revocation_key(user2))

        # Check that changing just the PK doesn't allow hijacking the other
        # user's account -- because the PK is included in the signature.
        data1 = self.decode_token(token1)
        data2 = self.decode_token(token2)
        self.assertEqual(data1[:4], packers.packer.pack_pk(user1.pk))
        self.assertEqual(data2[:4], packers.packer.pack_pk(user2.pk))

        # Check that changing just the primary key doesn't allow hijacking the
        # other user's account.
        token = self.encode_token(data2[:4] + data1[4:])

        user = parse_token(token, self.get_user)
        self.assertIsNone(user)
        self.assertLogsContain("Invalid token for user jane")
예제 #15
0
 def test_invalid_signature(self):
     token = create_token(self.user)
     # Alter signature, which is in bytes 5 1/3 - 18 2/3
     token = token[:6] + token[6:].lower()
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Invalid token for user john in default scope")
예제 #16
0
 def test_truncated_token_in_signature(self):
     token = create_token(self.user)
     # Signature is in bytes 10 2/3 - 24
     token = token[:12]
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot extract signature")
예제 #17
0
 def test_truncated_token_in_timestamp(self):
     token = create_token(self.user)
     # Timestamp is in bytes 5 1/3 - 10 2/3
     token = token[:8]
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot extract timestamp")
예제 #18
0
 def test_truncated_token_in_primary_key(self):
     token = create_token(self.user)
     # Primary key is in bytes 0 - 5 1/3
     token = token[:4]
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot extract primary key")
예제 #19
0
 def test_valid_max_age_token(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Valid token for user john in default scope")
예제 #20
0
 def test_invalid_token_in_scope(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user, scope="test")
     self.assertIsNone(user)
     self.assertLogsContain("Invalid token for user john in scope test")
예제 #21
0
 def test_invalid_base64_string(self):
     token = "deadbeef-"
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Bad token: cannot decode token")
예제 #22
0
 def test_custom_max_age(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user, max_age=300)
     self.assertEqual(user, self.user)
     self.assertLogsContain("Valid token for user john")
예제 #23
0
 def test_expired_max_age_token(self):
     token = create_token(self.user)
     self.assertTrue(detect_token(token))
     user = parse_token(token, self.get_user)
     self.assertIsNone(user)
     self.assertLogsContain("Expired token")