59 lines
1.8 KiB
Python
Executable File
59 lines
1.8 KiB
Python
Executable File
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from cognitive_agent.auth import (
|
|
AuthConfig,
|
|
SessionCodec,
|
|
SlidingWindowLimiter,
|
|
hash_password,
|
|
verify_password,
|
|
)
|
|
|
|
|
|
def auth_config() -> AuthConfig:
|
|
return AuthConfig(
|
|
enabled=True,
|
|
username="demo-user",
|
|
password_hash=hash_password(
|
|
"correct horse battery staple",
|
|
salt=b"0123456789abcdef",
|
|
iterations=100_000,
|
|
),
|
|
session_secret=b"s" * 64,
|
|
session_ttl_seconds=3600,
|
|
login_attempts=3,
|
|
login_window_seconds=60,
|
|
requests_per_minute=10,
|
|
trust_proxy_headers=False,
|
|
)
|
|
|
|
|
|
class AuthenticationUnitTests(unittest.TestCase):
|
|
def test_password_hash_verification(self) -> None:
|
|
encoded = auth_config().password_hash
|
|
|
|
self.assertTrue(verify_password("correct horse battery staple", encoded))
|
|
self.assertFalse(verify_password("wrong password", encoded))
|
|
self.assertNotIn("correct horse battery staple", encoded)
|
|
|
|
def test_signed_session_rejects_tampering_and_expiry(self) -> None:
|
|
codec = SessionCodec(auth_config())
|
|
token = codec.issue("demo-user", now=1000)
|
|
|
|
self.assertEqual(codec.verify(token, now=1001), "demo-user")
|
|
self.assertIsNone(codec.verify(token + "x", now=1001))
|
|
self.assertIsNone(codec.verify(token, now=4600))
|
|
|
|
def test_sliding_window_limiter_returns_retry_after(self) -> None:
|
|
limiter = SlidingWindowLimiter(limit=2, window_seconds=60)
|
|
|
|
limiter.record("client", now=100)
|
|
limiter.record("client", now=110)
|
|
self.assertEqual(limiter.retry_after("client", now=120), 40)
|
|
self.assertEqual(limiter.retry_after("client", now=161), 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|