From b734d95bc0035209437b592407be7e2a7570fc33 Mon Sep 17 00:00:00 2001 From: Lucas Coutinho Date: Wed, 13 May 2026 12:57:29 -0300 Subject: [PATCH] =?UTF-8?q?test(auth):=20add=20regression=20tests=20for=20?= =?UTF-8?q?HMAC=20migration=20bridge=20(32=E2=86=9264=20char)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_auth_sessions.py | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test_auth_sessions.py b/tests/test_auth_sessions.py index 9e95dedf..725e336b 100644 --- a/tests/test_auth_sessions.py +++ b/tests/test_auth_sessions.py @@ -130,6 +130,48 @@ class TestSessionInvalidation(unittest.TestCase): # Should not raise +class TestHmacMigrationBridge(unittest.TestCase): + """Verify the 32→64-char HMAC migration bridge in verify_session(). + + When create_session() was changed from hexdigest()[:32] to hexdigest(), + existing session cookies with 32-char signatures needed to remain valid. + These tests lock down the dual-length acceptance so a future refactor + doesn't accidentally drop it. + + These can be removed once session TTLs have expired (~30 days from the + deploy date of fix 3/3). + """ + + def setUp(self): + auth._sessions.clear() + + def test_legacy_truncated_sig_still_validates(self): + """A cookie signed with the old 32-char truncation must still verify. + + Simulates a session created by a pre-upgrade build where + hexdigest()[:32] was used. After upgrade to full 64-char HMAC, + this cookie must still be accepted (migration bridge). + """ + token = auth.secrets.token_hex(32) + auth._sessions[token] = time.time() + 3600 + legacy_sig = auth.hmac.new( + auth._signing_key(), token.encode(), auth.hashlib.sha256 + ).hexdigest()[:32] + cookie = f"{token}.{legacy_sig}" + self.assertTrue(auth.verify_session(cookie)) + + def test_full_sig_rejects_forged_prefix(self): + """A forged 32-char sig that is NOT the HMAC prefix must be rejected. + + Ensures the len(sig) == 32 guard prevents blind acceptance of + arbitrary short signatures. + """ + token = auth.secrets.token_hex(32) + auth._sessions[token] = time.time() + 3600 + forged = "a" * 32 + self.assertFalse(auth.verify_session(f"{token}.{forged}")) + + if __name__ == "__main__": unittest.main()