security: require verified email for admin + harden sessions
Admin (email allowlist) is now gated on a verified email and re-evaluated per request instead of trusting a frozen cookie flag; session max_age cut to 8h. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,30 @@ USER = {"sub": "sub-user", "email": "user@x.com", "name": "User", "is_admin": Fa
|
||||
ADMIN = {"sub": "sub-admin", "email": "admin@x.com", "name": "Admin", "is_admin": True}
|
||||
|
||||
|
||||
def test_current_user_admin_requires_verified_email():
|
||||
"""is_admin is recomputed per request and requires a VERIFIED allowlisted email."""
|
||||
from types import SimpleNamespace
|
||||
|
||||
cfg = SimpleNamespace(admin_emails=frozenset({"admin@x.com"}))
|
||||
|
||||
def req(session_user):
|
||||
return SimpleNamespace(
|
||||
session={"user": session_user} if session_user else {},
|
||||
app=SimpleNamespace(state=SimpleNamespace(cfg=cfg)),
|
||||
)
|
||||
|
||||
# verified + allowlisted -> admin
|
||||
assert appmod.current_user(req({"email": "admin@x.com", "email_verified": True}))["is_admin"] is True
|
||||
# allowlisted but NOT verified -> not admin (the security fix)
|
||||
assert appmod.current_user(req({"email": "admin@x.com", "email_verified": False}))["is_admin"] is False
|
||||
# missing email_verified claim -> not admin
|
||||
assert appmod.current_user(req({"email": "admin@x.com"}))["is_admin"] is False
|
||||
# verified but not on the allowlist -> not admin
|
||||
assert appmod.current_user(req({"email": "user@x.com", "email_verified": True}))["is_admin"] is False
|
||||
# no session user -> None
|
||||
assert appmod.current_user(req(None)) is None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app_url(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("INTERVALS_ENC_KEY", KEY)
|
||||
|
||||
Reference in New Issue
Block a user