feat(auth): generic HMAC signed-cookie module for operator auth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 19:01:16 +00:00
parent 37e6ca55c1
commit 8e817ec48d
2 changed files with 113 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
# tests/test_operator_cookies.py
import time
import base64
import json
from backend.auth_cookies import sign, read
def test_sign_then_read_round_trips():
now = int(time.time())
raw = sign({"uid": "abc", "iat": now})
data = read(raw, max_age=3600)
assert data == {"uid": "abc", "iat": now}
def test_tampered_signature_is_rejected():
raw = sign({"uid": "abc", "iat": int(time.time())})
body, _sig = raw.rsplit(".", 1)
assert read(body + ".deadbeef", max_age=3600) is None
def test_tampered_body_is_rejected():
raw = sign({"uid": "abc", "iat": int(time.time())})
body, sig = raw.rsplit(".", 1)
forged = base64.urlsafe_b64encode(json.dumps({"uid": "evil", "iat": int(time.time())}).encode()).decode()
assert read(forged + "." + sig, max_age=3600) is None
def test_expired_by_iat_is_rejected():
raw = sign({"uid": "abc", "iat": int(time.time()) - 10_000})
assert read(raw, max_age=3600) is None
def test_garbage_input_is_none_not_raise():
assert read("not-a-cookie", max_age=3600) is None
assert read("", max_age=3600) is None
assert read(None, max_age=3600) is None
def test_wrong_secret_is_rejected(monkeypatch):
import backend.auth_cookies as ac
monkeypatch.setattr(ac, "SECRET_KEY", "secret-A")
raw = ac.sign({"uid": "x", "iat": int(time.time())})
monkeypatch.setattr(ac, "SECRET_KEY", "secret-B")
assert ac.read(raw, max_age=3600) is None
def test_future_dated_iat_is_rejected():
raw = sign({"uid": "x", "iat": int(time.time()) + 10_000})
assert read(raw, max_age=3600) is None